当接口不从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;
在这里寻找最好的(或好的)做法。
答案 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 answer和this 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方法。