IDisposable实现非IDisposable接口

时间:2011-05-04 21:38:11

标签: .net oop idisposable

接口不从IDisposable 继承时,正确处理接口默认实现的最佳方法是什么?例如,假设我想要

public class FooGetter : IDisposable {

    private IFooProvider fooProvider = MyContainer.GetDefault<IFooProvider>();
    ...
    public void Dispose(){
         ...
         if (fooProvider != null) fooProvider.Dispose(); // obviously has compile error here
    }
}

恰好,IFooProvider的默认实现是IDisposable,但IFooProvider接口不从IDisposable继承。我应该如何/在哪里处理它?<​​/ p>

问题不仅仅在于依赖注入容器;它也适用于紧密耦合的依赖:

private IFooProvider fooProvider = new PatrickProvider();

在这种情况下,我可以保留另一个引用,以便稍后可以Dispose()它,但这看起来真的很笨拙:

private PatrickProvider defaultFooProvider = new PatrickProvider();
private IFooProvider fooProvider = defaultFooProvider;

在这里寻找最好的(或好的)做法。

4 个答案:

答案 0 :(得分:2)

使用DI容器时的最佳做法是让DI容器为您处理对象的生命周期。如果你将DI容器用作服务定位器(boo!anti-pattern !!),就像你似乎正在使用MyContainer.GetDefault一样,这是不可能的,但是如果你通过构造函数注入正确地注入了依赖项,那么它会运作良好。

对于紧密耦合的依赖关系,你必须做一些愚蠢的事情,比如

using(fooProvider as IDisposable)
{
    // Code that uses fooProvider
}

我认为(但并非100%肯定)using如果通过null将无效,所以无论fooProvider是否实施IDisposable,这都会有效。< / p>

有很好的讨论IDisposable,因为它与依赖关系是马克塞曼的Dependency Injection in .NET第8章中的DI。

答案 1 :(得分:1)

您可以执行运行时检查对象是否实现IDisposable,如果是,请将其丢弃:

public class FooGetter : IDisposable
{
    private IFooProvider fooProvider = MyContainer.GetDefault<IFooProvider>();
    ...
    public void Dispose()
    {
         IDisposable disposable = fooProvider as IDisposable;

         if (disposable != null)
         {
             fooProvider.Dispose();
         }
    }
}

你仍然需要了解你的接口的实现可能是一次性的,否则代码有点无意义,但对于你的情况,它将确保在具有它的实现上调用Dispose()

理想情况下,您的界面应该来自IDisposable,以表明其合同的一部分是您必须在完成后处理它,但我承认实际上这可能并非总是可行。

答案 2 :(得分:1)

对我而言,似乎有一些事情需要考虑。

首先,想象一个接口IFoo是完全合理的,其中一些实现可能具有处理或清理执行的资源而其他实现可能没有;因此,有些人认为不使IFoo继承IDisposable是合理的。

public interface IFoo{
    // ...
}

// Has no cleanup or resources
public interface Foo1:IFoo{
    // ...
}

// Does have resources to release and cleanup to perform
public interface Foo2:IFoo,IDisposable{
    // ...
}

请参阅this answerthis discussion,了解实现IDisposable的选择应该取决于具体类还是抽象类/接口。 编辑:打破本段的大部分内容,因为在回顾讨论之后,我看到“有界面定义”方面的好点,并将重新评估我的观点。另外,这个决定与被问到的问题并不真正相关。

现在除此之外,如果您有IFoo x,并且某些实现实现了IDisposable而其他实现没有,则可以检查x是否实现了IDisposable。在它的情况下,妥善处理它。如果没有,那么你应该相信,编写x的IFooProvider实现的人没有实现IDisposable,因为你不需要调用它,并且知道你已经尽力而为。

IFoo x; 
//x = whatever
if (x is IDisposable)
{
    ((IDisposable)x).Dispose();
} 

答案 3 :(得分:0)

如果您正在定义IFooProvider,为什么不让它继承IDispoable?如果有人想出一个不需要清理的实现,它可以简单地实现一个空的Dispose方法。