C# 管理一次性类依赖注入

C# 管理一次性类依赖注入,c#,dependency-injection,ninject,lifecycle,C#,Dependency Injection,Ninject,Lifecycle,我想知道如何使用DI管理对象。假设我有一节课 class Foo : IFoo, IDisposable { // ... } 然后这个类被注入到另一个类中 class Bar { public Bar(IFoo foo) { this.Foo = foo } IFoo Foo { get; set; } } 然后将其绑定到某个范围(我的示例使用MVC和Ninject) this.Bind().To().InRequestScope

我想知道如何使用DI管理对象。假设我有一节课

class Foo : IFoo, IDisposable
{
    // ...
}
然后这个类被注入到另一个类中

class Bar
{
    public Bar(IFoo foo)
    {
        this.Foo = foo
    }

    IFoo Foo { get; set; }
 }
然后将其绑定到某个范围(我的示例使用MVC和Ninject)

this.Bind().To().InRequestScope();

我想知道,既然依赖注入框架处理
Foo
的生命周期,我应该在
Bar
中实现IDisTable吗?我的想法是DI正在管理
Foo
的生命周期,所以不要碰它,以防另一个类正在使用
Foo
。另外,由于一次性对象作为构造函数参数传递到
Bar
,因此
Bar
不会包装一次性对象,因此它不知道
Bar
的调用方在
Bar
被垃圾收集后想要如何使用
Foo
。这是对的吗?

是的,你的假设是正确的。Ninject将为您处理该对象

这是管理生命周期的一般问题。基本规则是,创建对象的人拥有该实例的所有权。所有者应处置/销毁该实例。所有权可以传递给其他人,这使得“其他人”有责任销毁该实例

在您的情况下,Foo实例不是由Bar创建的,因此Bar不负责处理该实例。由于Ninject为您创建了该实例,因此它负责清理该实例

所有权可以传递,但这必须是明确的。明确所有权传递的一个很好的例子是Factory设计模式:

IFoo CreateNewFoo();
尽管此方法创建了新的
IFoo
实例,但很明显,他将所有权传递回调用方


传递所有权的坏方法的一个很好的例子是.NET的
StreamReader
类。它在构造函数中接受一个一次性对象,但它拥有所有权。尽管文档声明类处理给定的对象,但这种行为让许多开发人员眼花缭乱,因为它违反了所有权的一般规则。微软最终在.NET4.5中通过添加一个允许禁止处理给定流的ctor重载修复了这个问题

Nicholas Blumhardt在这个主题上发表了一篇很好的文章,以Autofact为例,但一般来说是适用的。看看一些MSDN文章,微软似乎会同时做两件事:(StremReader)“当调用StreamReader.Dispose时,StreamReader对象调用提供的流对象上的Dispose()”但是(位图)“您必须在位图的生命周期内保持流开放。”我在测试时意识到了这一点。我想我的主要问题是,谁负责处理对象。我基于搜索得出的结论是,创建一次性对象的对象负责处理对象。因此,在本例中,Ninject。
IFoo CreateNewFoo();