IOC容器和IDisposable

时间:2010-04-14 03:22:02

标签: ioc-container idisposable

我建议使用IOC容器时,我应该改变它:

class Foobar: IFoobar, IDisposable {};

进入这个:

interface IFoobar: IDisposable{};
class Foobar : IFoobar{};

我想知道这是否正常,或者它是否解决了一个问题并创造了另一个问题。它肯定解决了我非常想要这样做的问题:

using( IFoobar = myContainer.Resolve<IFoobar>() )
{ ... }

现在我知道任何替代品都不会导致运行时错误。

另一方面,现在我的所有模拟对象也必须处理IDisposable。我是对的,大多数任何模拟框架都能轻松处理这个问题吗?如果是,那么也许这不是问题。

或者是吗?我应该注意另一个隐藏的问题吗?我肯定会发现,如果我使用IOC容器而不是单元测试/模拟,但是为了真正的服务独立性,那么这可能是一个问题,因为可能只有我的一个可交换服务实际上处理非托管资源(现在我'我必须在这些其他服务中实现空的“IDispose”操作。)

即使是后一个问题,我想我可以忍受,为了获得使用上面演示的“使用”声明的能力。但是,我是遵循一个流行的惯例,还是我错过了一个完全不同的更好的解决方案?

1 个答案:

答案 0 :(得分:11)

从IDisposable中获取界面在我看来是一种设计气味,表明 Leaky Abstraction 。正如尼古拉斯·布鲁姆哈特put it

  接口[...]通常不应该是一次性的。定义接口的人无法预见它的所有可能实现 - 您总是可以提供几乎任何接口的一次性实现。

考虑为什么要将IDisposable添加到您的界面。这可能是因为您有特定的实现。因此,实现泄漏到抽象中。

值得盐的DI容器应该知道它何时创建一次性类型的实例。当您随后要求容器释放对象图时,它应自动处理一次性组件(如果他们的生活方式时间已经过时)。

我知道至少Castle Windsor和Autofac会这样做。

所以在你的情况下,你应该保持你的类型:

class Foobar: IFoobar, IDisposable {};

您可能会发现Nicholas Blumhardt的帖子The Relationship Zoo也很有趣 - 特别是有关Owned<T>的讨论。