你如何协调IDisposable和IoC?

Mr.*_*tty 41 c# idisposable inversion-of-control unity-container

我终于在C#中围绕IoC和DI缠绕我的头,并且正在努力解决一些问题.我正在使用Unity容器,但我认为这个问题适用范围更广.

使用IoC容器来分配实现IDisposable的实例让我感到害怕!你怎么知道你应该Dispose()?该实例可能是专门为您创建的(因此您应该Dispose()它),或者它可能是其生命周期在其他地方管理的实例(因此您最好不要).代码中没有任何内容告诉您,实际上这可能会根据配置发生变化!这对我来说似乎是致命的.

任何IoC专家都可以描述处理这种模糊性的好方法吗?

Mik*_*nty 17

你绝对不想在注入你的类的对象上调用Dispose().你不能假设你是唯一的消费者.最好的办法是将非托管对象包装在某个托管界面中:

public class ManagedFileReader : IManagedFileReader
{
    public string Read(string path)
    {
        using (StreamReader reader = File.OpenRead(path))
        {
            return reader.ReadToEnd();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这只是一个例子,如果我试图将文本文件读入字符串,我会使用File.ReadAllText(path).

另一种方法是注入工厂并自己管理对象:

public void DoSomething()
{
    using (var resourceThatShouldBeDisposed = injectedFactory.CreateResource())
    {
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @先生.Putty - 依赖注入并不能消除对工厂的需求,它只是让一个(ab)使用它们是不必要的.例如,当您在运行时之前不知道具体依赖项的类型,或者对于昂贵的条件依赖项(您可能甚至不需要需要大量资源来创建的对象)时,您可能希望注入工厂而不是对象本身.根据您的DI框架对IDisposable的支持,工厂注入可能是最好的方式 - 它肯定比许多替代方案更透明.(1) (8认同)
  • 但我确实想要注入IDisposable对象,而且,我可能需要或可能不需要在注入位置Dispose(),具体取决于配置.您的第一个示例在临时访问基础资源时有效,但如果资源更持久,则无效.在第二个例子中,以这种方式注入工厂对我来说似乎很奇怪; 这首先是IoC模型的主要功能之一.如果我将IoC应用于这个概念,我似乎最终回到原来的问题.我认为容器本身需要参与这个,即自动转换. (2认同)

Sam*_*ack 7

AutoFac通过允许创建嵌套容器来处理此问题.容器完成后,它会自动处理其中的所有IDisposable对象.更多这里.

..当您解析服务时,Autofac会跟踪已解析的一次性(IDisposable)组件.在工作单元结束时,您将处置关联的生命周期范围,Autofac将自动清理/处置已解析的服务.