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());