【发布时间】:2010-12-06 04:32:33
【问题描述】:
所以我正在开发我的 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 将项目添加到容器时,还会添加一个事件处理程序,以便当它被 Disposed(通过包装器)时,框架会将其从基础集合中删除。
我实际上已经实现了这个并且它通过了单元测试,但我正在寻找关于它可能被破坏的地方的意见,或者如何使它对消费开发者更加“友好”。
编辑 1
由于有关于如何使用 Disposing 事件的问题,这里有一些代码(修剪到重要的部分):
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);
}
【问题讨论】:
-
我们能否更全面地描述正在添加的特定功能?人们想要这个的用例是什么,您作为(IoC 框架)或最终用户的事件处理程序是什么?等等。
-
用例是添加自动化生命周期管理。如果您将 IDisposable 项添加到集合并稍后调用 Dispose,则它实际上永远不会被清理,因为容器拥有对象的根。这个想法是,您可以在对象上调用 Dispose ,而无需返回集合来查找它,并让它自动导致从容器集合中删除。该事件由框架纯粹在内部使用(它甚至被标记为内部,以免在外部使用)并且处理程序将其从集合中删除。
-
为了清楚起见,我更新了问题以添加事件处理。
-
所以消费者已经处理掉了这个对象,他们想确保你不再持有它?如果他们再次要求会发生什么,你会做一个新的吗?就代码而言,我唯一能注意到的不寻常之处是您正在通过事件处理程序从终结器中使用 GC 线程,因此请小心该代码! :)
-
@ctacke:“如果您将 IDisposable 项添加到集合中,然后调用 Dispose,它实际上永远不会被清理,因为容器拥有对象的根。”持有引用仅适用于 GC。处置非托管资源应该是开发人员的责任。调用 Dispose 将立即进行清理,而不管存在哪些其他引用。
标签: c# compact-framework dependency-injection ioc-container opennetcf.ioc