C# 一次性注册表:好模式?

C# 一次性注册表:好模式?,c#,idisposable,C#,Idisposable,想象一个: public class Global : IDisposable { private static readonly List<IDisposable> Disposables = new List<IDisposable>(); public void ApplicationStart() { var heavyLifter = new HeavyLifter(); Disposables.Add

想象一个:

public class Global : IDisposable 
{
    private static readonly List<IDisposable> Disposables = new List<IDisposable>();

    public void ApplicationStart()
    {
        var heavyLifter = new HeavyLifter();
        Disposables.Add(heavyLifter);
            // register a few more
    }

    public void Dispose()
    {
        Disposables.ForEach(d => d.Dispose());
    }
}
公共类全局:IDisposable
{
private static readonly List Disposables=new List();
公共void应用程序启动()
{
var heavyLifter=新的heavyLifter();
一次性物品。添加(较重);
//再注册一些
}
公共空间处置()
{
一次性使用。ForEach(d=>d.Dispose());
}
}

我对IDisposable有点缺乏经验。这是一种可行的模式吗?

您的代码意味着HeavyLifeter实现了IDisposable。因此,您只需在应用程序的End eventhandler中调用其Dispose方法。

您的代码意味着HeavyLifeter实现了IDisposable。因此,您只需在应用程序的End eventhandler中调用其Dispose方法。

据我所知,您正在创建一个组件,该组件将使用(我假设)多个资源来实现
IDisposable
,您只是在寻找一种方法来维护组件中的
IDisposable
对象列表,并在列表中迭代,而不是按名称调用每个项的
Dispose
,对吗


如果是这样,那也没什么错。但是,您的列表不应该是静态的,而应该是每个实例的。

据我所知,您正在创建一个组件,该组件将使用(我假设)多个资源来实现
IDisposable
,您只是在寻找一种方法来维护组件中的
IDisposable
对象列表,并在列表中迭代,而不是按名称调用每个项的
Dispose
,对吗


如果是这样,那也没什么错。但是,您的列表不应该是静态的,而应该是每个实例的。

在一个级别上,IOC容器(如Unity)可以提供这种功能:

您可以将创建对象的责任委托给IOC容器,并可以指定LifeTimeManager选项。这可以包括在容器中注册以供以后处理,例如在应用程序关闭或表单关闭时调用容器上的处理

对于寿命较短的对象,您可能希望自己管理处置,但对于寿命较长的对象,具有对象处置的IOC类型存储库模式可以很好地工作。对我来说效果很好。:)


不过,很好地理解处置始终是一件好事。

在一个级别上,像Unity这样的IOC容器可以提供这种功能:

您可以将创建对象的责任委托给IOC容器,并可以指定LifeTimeManager选项。这可以包括在容器中注册以供以后处理,例如在应用程序关闭或表单关闭时调用容器上的处理

对于寿命较短的对象,您可能希望自己管理处置,但对于寿命较长的对象,具有对象处置的IOC类型存储库模式可以很好地工作。对我来说效果很好。:)


不过,很好地理解Dispose始终是一件好事。

您的工作是基于这样的假设,即外部类将对对象的生存期有专门的了解,以便它在正确的时间调用Dispose()。这很少起作用,只有客户机代码知道何时处理对象


使用编写的类,您可以实现完全相反的目标,使对象的活动时间比需要的时间长得多。甚至垃圾收集器也不能运行终结器,因为您会一直保留对象,直到某个神奇的时刻,所有对象都准备好被处置。通常的术语是“内存泄漏”。不要这样做。

您的工作假设是外部类对对象的生存期有特殊的了解,以便它在正确的时间调用Dispose()。这很少起作用,只有客户机代码知道何时处理对象


使用编写的类,您可以实现完全相反的目标,使对象的活动时间比需要的时间长得多。甚至垃圾收集器也不能运行终结器,因为您会一直保留对象,直到某个神奇的时刻,所有对象都准备好被处置。通常的术语是“内存泄漏”。不要这样做。

表面上看,当您无法使处理线程安全时(例如,当与COM对象交谈时,必须在同一线程上释放),这种方法是有意义的。然而,在实践中,您会发现这种方法会导致对象的寿命超过其应有的寿命

我将努力使处理线程安全,这样您就可以从终结器调用
Dispose
,实现真正的自动生命周期管理。您必须小心,因为可能不适合某些类型的资源,如文件或网络句柄,这可能需要更严格的控制。否则,这是该问题的最佳解决方案

如果处置必须在同一条线上进行,那么你就有点麻烦了。如果需要处理的对象位于模型层(如在业务规则对象中),则很可能它的上面有UI层,需要复杂的逻辑来处理它(如关闭窗口后的事件)。这是一种失去/失去的情况,是在永久存在的对象(如原始解决方案)和复杂的处理逻辑(很快就会变得丑陋)之间进行选择

也许可以做些实验。您可以将一次性资源分离到它自己的类中,并让工厂维护对它的强引用。资源对象维护对业务对象的弱引用。当业务对象最终确定时,
WeakReference
将返回
null
,从而使您能够传递一次性物品并转储不再需要的物品

public class Global {
    private static readonly List<Resource> Disposables = new List<Resource>();

    public HeavyLifter GetHeavyLifter()
    {
        var resource = new HeavyLifterResource();
        var heavyLifter = new HeavyLifter(resource);
        resource.BusinessObject = heavyLifter;
        Disposables.Add(resource);
    }

    public void DisposeAll()
    {
        Disposables.ForEach(d => d.CleanUp());
    }
}

public abstract class Resource : IDisposable {

    WeakReference<object> m_BusinessObject;
    public WeakReference<object> BusinessObject {get;set;}

    public CleanUp() {
      if (!m_BusinessObject.IsAlive)
        Dispose();
    }
}

public HeavyLifter {
    public HeavyLifter (Disposable d) {
      m_resourceObj = d;
    }

    HeavyLifterResource m_resourceObj;
}

public class HeavyLifterResource :Resource {
    public void Dispose() {
      //disposal
    }
}
公共类全局{
private static readonly List Disposables=new List();
公共重磅炸弹
DisposableThing Foo;  // At one point in the class
...
Foo  = new DisposableThing();  // In the constructor
...
DisposableThing.Dispose;  // In `Dispose(bool)`
DisposableThing = DisposeProtector.Register(new DisposableThing());