DI:处理 IDisposable 对象的生命周期
-
21-09-2019 - |
题
所以我正在开发我的 DI/IoC 容器 OpenNETCF.IoC 我有一个(合理的)功能请求,为容器集合中的 IDisposable 项目添加某种形式的生命周期管理。
我目前的想法是,由于我无法查询对象以查看它是否已被处置,并且我无法获取该对象何时被处置的事件,因此我必须为开发人员想要的对象创建某种形式的包装器框架来管理。
现在可以使用 AddNew 添加对象(为了简单起见,我们假设只有一个重载并且没有 Add):
public TTypeToBuild AddNew<TTypeToBuild>() { ... }
我正在考虑添加一种新方法(很好的一组方法,但你明白了):
public DisposableWrappedObject<IDisposable> AddNewDisposable<TTypeToBuild>()
where TTypeToBuild : class, IDisposable
{
...
}
DisposableWrappedObject 如下所示:
public class DisposableWrappedObject<T>
where T : class, IDisposable
{
public bool Disposed { get; private set; }
public T Instance { get; private set; }
internal event EventHandler<GenericEventArgs<IDisposable>> Disposing;
internal DisposableWrappedObject(T disposableObject)
{
if (disposableObject == null) throw new ArgumentNullException();
Instance = disposableObject;
}
~DisposableWrappedObject()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
lock(this)
{
if(Disposed) return;
EventHandler<GenericEventArgs<IDisposable>> handler = Disposing;
if(handler != null)
{
Disposing(this, new GenericEventArgs<IDisposable>(Instance));
}
Instance.Dispose();
Disposed = true;
}
}
}
现在,当通过 AddNewDIsposable 将项目添加到容器时,还会添加一个事件处理程序,以便当它(通过包装器)获得 Dispose 时,框架会将其从底层集合中删除。
我实际上已经实现了这个并且它通过了单元测试,但我正在寻找关于这个可能被破坏的地方的意见,或者如何使其对消费开发人员更加“友好”。
编辑1
由于存在有关如何使用 Dispose 事件的问题,因此这里有一些代码(根据重要内容进行了修剪):
private object AddNew(Type typeToBuild, string id, bool wrapDisposables)
{
....
object instance = ObjectFactory.CreateObject(typeToBuild, m_root);
if ((wrapDisposables) && (instance is IDisposable))
{
DisposableWrappedObject<IDisposable> dispInstance = new
DisposableWrappedObject<IDisposable>(instance as IDisposable);
dispInstance.Disposing += new
EventHandler<GenericEventArgs<IDisposable>>(DisposableItemHandler);
Add(dispInstance as TItem, id, expectNullId);
instance = dispInstance;
}
....
return instance;
}
private void DisposableItemHandler(object sender, GenericEventArgs<IDisposable> e)
{
var key = m_items.FirstOrDefault(i => i.Value == sender).Key;
if(key == null) return;
m_items.Remove(key);
}
解决方案
也许我遗漏了一些东西,但为什么要向 API 添加新方法呢?当一个对象被添加到容器中时,您可以进行 as-cast 来检查它是否是 IDisposable,如果是,则进行适当的处理。
我还想知道你是否需要析构函数。假设容器是 IDisposable(如 Unity 的),您可以实现 基本处置模式 并节省大量GC开销。
一些可能适用的问题:
不隶属于 StackOverflow