DI:处理IDisposable的对象的生活 [英] DI: Handling Life of IDisposable Objects

查看:178
本文介绍了DI:处理IDisposable的对象的生活的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我的工作我的DI / IoC容器 OpenNETCF.IoC 和我有一个(合理)功能要求添加某种形式的生命周期管理在容器的集合IDisposable的项目。



我目前的想法是这样的,因为我不能查询对象,看看它是否被释放,并我不能当它被释放的事件,我必须创建某种形式的包装器,开发者希望框架来管理对象。



现在对象可以的AddNew添加(为简单起见,我们假定只有一个过载,不存在添加):

 公开TTypeToBuild的AddNew< TTypeToBuild>(){...} 

我正在考虑是增加一个新的方法(以及他们的群体,但你得到的图片):

 公共DisposableWrappedObject<&的IDisposable GT; AddNewDisposable< TTypeToBuild>()
式TTypeToBuild:类,IDisposable的
{

}

凡DisposableWrappedObject看起来是这样的:

 公共类DisposableWrappedObject< T> 
,其中T:类,IDisposable的
{
公共BOOL处置{搞定;私人集; }
公共牛逼实例{搞定;私人集; }

内部事件的EventHandler< GenericEventArgs<&的IDisposable GT;>处置;

内部DisposableWrappedObject(T disposableObject)
{
如果(disposableObject == NULL)抛出新的ArgumentNullException();

实例= disposableObject;
}

〜DisposableWrappedObject()
{
的Dispose(假);
}

公共无效的Dispose()
{
的Dispose(真);
}

受保护的虚拟无效的Dispose(BOOL处置)
{
锁(本)
{
如果(处置)回报;

&事件处理LT; GenericEventArgs<&的IDisposable GT;>处理处置=;
如果(处理!= NULL)
{
处置(这一点,新GenericEventArgs<&的IDisposable GT;(实例));
}

Instance.Dispose();

处置= TRUE;
}
}
}

现在,当一个项目得到加到通过AddNewDIsposable容器中,事件处理程序也被添加,以便当它被处理完毕(通过包装器)的框架内从底层集合中移除。



我确实有这种实现,它通过单元测试,但我在寻找的意见在哪里,这可能被打破,不然怎么可能会变得更加友好的消费开发商。



修改1



由于是如何被使用的处置事件的问题,这里的一些代码(修剪到什么是重要的):

 私有对象的AddNew(类型typeToBuild,字符串ID,布尔wrapDisposables)
{
....

对象实例= ObjectFactory.CreateObject(typeToBuild,m_root);

如果((wrapDisposables)及及(实例IDisposable接口))
{
DisposableWrappedObject<&的IDisposable GT; dispInstance =新的
DisposableWrappedObject<&的IDisposable GT;(实例作为IDisposable接口);
dispInstance.Disposing + =新的
&事件处理LT; GenericEventArgs<&的IDisposable GT;>(DisposableItemHandler);
添加(dispInstance为TItem,ID,expectNullId);
实例= dispInstance;
}

....

返回实例;
}

私人无效DisposableItemHandler(对象发件人,GenericEventArgs< IDisposable的> E)
{
VAR键= m_items.FirstOrDefault(I => i.Value = =发送者)。重点;
如果(键== NULL)回报;
m_items.Remove(键);
}


解决方案

也许我失去了一些东西,但为什么新的方法添加到API?当一个对象被添加到容器中,你可以铸以检查它是否是IDisposable接口,如果是这样适当地处理它。



我也想知道,如果你需要的析构函数。假设该容器是IDisposable接口(如Unity的),你可以只实施的基础Dispose模式并节省了大量的GC开销



有些问题可能适用:




So I'm working on my DI/IoC Container OpenNETCF.IoC and I've got a (reasonable) feature request to add some form of lifecycle management for IDisposable items in the container collections.

My current thinking is that, since I can't query an object to see if it's been disposed, and I can't get an event for when it's been disposed, that I have to create some form of wrapper for objects that a developer wants the framework to manage.

Right now objects can be added with AddNew (for simplicity sake we'll assume there's only one overload and there is no Add):

public TTypeToBuild AddNew<TTypeToBuild>() { ... }

What I'm considering is adding a new method (well group of them, but you get the picture):

public DisposableWrappedObject<IDisposable> AddNewDisposable<TTypeToBuild>()
    where TTypeToBuild : class, IDisposable
{
    ...
}

Where the DisposableWrappedObject looks like this:

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;
        }
    }
}

Now, when an items gets added to the container via AddNewDIsposable, an eventhandler is also added so that when it gets Disposed (via the wrapper) the framework removes it from the underlying collection.

I actually have this implemented and it's passing the unit tests, but I'm looking for opinions on where this might be broken, or how it might be made more "friendly" to the consuming developer.

EDIT 1

Since there was a question on how the Disposing event is used, here's some code (trimmed to what's important):

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

解决方案

Maybe I'm missing something, but why add new methods to the API? When an object is added to the container, you could as-cast to check if it's IDisposable and handle it appropriately if so.

I'm also wondering if you need the destructor. Presuming the container is IDisposable (like Unity's), you could just implement the Basic Dispose Pattern and save a lot of GC overhead.

Some questions that may be applicable:

这篇关于DI:处理IDisposable的对象的生活的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆