.net – 依赖注入和IDisposable
我对使用Autofac的IDisposable实现中的Dispose()方法有点困惑
说我的对象有一定的深度: >控制器取决于IManager; 这导致以下对象图: new Controller( new Manager( new Repository( new Session()))); 我是否还需要使我的Manager和Repository实现IDisposable,并在Controller中调用Manager.Dispose(),在Manager中调用Repository.Dispose()等,或者Autofac会自动知道我的调用堆栈中哪些对象需要正确处理? Controller对象已经是IDisposable,因为它派生自基本ASP.NET Web API控制器
资源的一般规则是:
这意味着如果一个类拥有一个资源,它应该以与它创建它相同的方法处置它,或者如果这不可能,这通常意味着拥有类必须实现IDisposable,因此它可以将资源部署在其中处理方法. 但重要的是要注意,一般来说,如果一个类负责创建它,那么它只拥有一个资源.但是当注入资源时,这意味着该资源在消费者之前就已存在.消费者没有创建资源,在这种情况下应该不处理它.虽然我们可以将资源的所有权传递给使用者(并在类的文档中传递所有权的传递),但通常不应传递所有权,因为这会使代码复杂化并使应用程序非常脆弱. 虽然在某些情况下转移对象所有权的策略可能有意义,例如对于可重用API的一部分类型(如System.IO.StreamReader),在处理作为对象图的一部分的组件时总是不好的(我们所谓的injectables).我将在下面解释原因. 因此,即使您的Controller依赖于需要处理的依赖项,您的控制器也不应该丢弃它们.原因很简单: >由于消费者没有创建这种依赖关系,因此不知道该依赖关系的预期生命周期是什么.很可能依赖性应该比消费者的生命周期长.在这种情况下让消费者处理该依赖将导致应用程序中的错误,因为下一个控制器将获得已经处置的依赖关系,这将导致抛出ObjectDisposedException. 所以相反,我们应该只让实现实现IDisposable.这使得抽象的任何消费者都不会怀疑它是否应该调用Dispose(因为没有Dispose方法来调用抽象). 现在因为只有实现实现了IDisposable,并且只有你的Composition Root创建了这个实现,所以它是组合根负责它的处理.如果你的DI容器创建了这个资源,它也应该处理它. Autofac实际上会为您做到这一点.你可以轻松测试这个.如果您在不使用DI容器(a.k.a.Pure DI)的情况下连接对象图形,则意味着您必须自己在组合根中处理这些对象. 要意识到这会使您的代码更简单.在抽象上实现IDisposable并让消费者处理它们的依赖关系将导致IDisposable像病毒一样通过你的系统传播(就像asynchronous programming spreads out like a virus一样污染你的代码库). 它展开,因为您总是可以想到需要清理其资源的抽象实现,因此您必须在每个抽象上实现IDisposable.这意味着每个需要一个或多个依赖项的实现也必须实现IDisposable,这会爬上对象图.这为系统中的每个类增加了大量代码和不必要的复杂性. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |