代码之家  ›  专栏  ›  技术社区  ›  dan-kli

如何正确处理在未实现IDisposable的已注册C#服务中保留的实例?

  •  0
  • dan-kli  · 技术社区  · 3 年前

    假设我有以下C#类 ClassA :

    public class ClassA
    {
        private readonly ClassB _b;
    
        public ClassA(ClassB b)
        {
            _b = b;
        }
    }
    

    此类持有对的实例的引用 ClassB ,实现 IDisposable :

    public class ClassB : IDisposable
    {
        public void Dispose()
        {
            // dispose
        }
    }
    

    现在,我注册 A类 通过依赖项注入作为服务,并创建和传递 B类 对它:

    services.AddSingleton(service => new ClassA(new ClassB()));
    

    在服务寿命结束时 Dispose() B类的方法被称为?根据 this stackoverflow post regarding the disposal of singleton instances 如果 A类 还将实施 IDisposable ,然后 Dispose() 方法 A类 也会接到电话。我是否也必须为实现接口 A类 ,并调用 Dispose() 属于 B类 在 Dispose() 属于 A类 ?或者我能以某种方式确信 Dispose() 方法 B类 在未实现的情况下被调用 IDisposable 在里面 A类 ?

    编辑:我认为Philip Stuyck的答案是正确的,因为它似乎为这个问题推荐了最简单的解决方案。至于我的问题 是 Dispose() 方法 B类 打过电话吗? ,我认为下面的讨论清楚地表明,它不被调用。相反,GC会清理 B类 通过调用 Finalize method instead of the Dispose method 在上面。

    1 回复  |  直到 3 年前
        1
  •  4
  •   Steven    3 年前

    如果你改变了将东西注册到控制倒置容器的方式,那么你根本不必实现idispoable:

    services.AddSingleton<ClassB>(ClassB);
    services.AddSingleton<ClassA>(ClassA);
    

    当您请求ClassA的实例时,它会查看构造函数并发现它需要classB。因此,您让容器解析ClassA,而不是自己控制它。

    然后,当应用程序关闭时,将根据需要在ClassB上调用dispose

    进一步的改进可以通过对控制进行反转来完成,并为类A和类B制作接口。然后,ClassA将包含对接口的引用,而不是对类的引用。这就是依赖反转的全部内容。

        2
  •  1
  •   Lajos Arpad    3 年前

    根据您当前的设置, ClassA 具有的数据成员 ClassB ,后者是 IDisposable 。每当你有 A类 对象 B类 是实例化的,因此您应该确保 ClassA implements IDisposable 并处置其 B类 成员(只要它存在),或者,您可以选择Philip Stuyck建议的IoC(控制反转)方法,然后,由于反转,您不需要处理 B类 成员