Pregunta

Así que estoy trabajando en mi DI / COI de contenedores OpenNETCF.IoC y tengo un (razonable ) solicitud de función para añadir algún tipo de gestión de ciclo de vida para los artículos IDisposable en las colecciones de contenedores.

Mi pensamiento actual es que, ya que no puedo consultar un objeto para ver si se ha dispuesto, y no puedo conseguir un evento para cuando se ha dispuesto, que tengo que crear algún tipo de contenedor para objetos que un desarrollador quiere que el marco para la gestión.

En este momento los objetos pueden ser añadido con AñadirNuevo (por razones de simplicidad asumiremos que sólo hay una sobrecarga y no hay Agregar):

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

Lo que estoy considerando es la adición de un nuevo método (también grupo de ellos, pero se obtiene la imagen):

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

Cuando el DisposableWrappedObject se ve así:

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

Ahora, cuando un elementos se agrega al recipiente a través de AddNewDIsposable, se añadió también un manejador de sucesos de modo que cuando se Dispuesta (a través de la envoltura) el marco quita de la colección subyacente.

En realidad tengo esta implementado y es pasar las pruebas de unidad, pero estoy en busca de comentarios sobre dónde podría ser roto, o cómo podría hacerse más "amigable" para el desarrollador que consume.

EDIT 1

Dado que no era una cuestión de cómo se utiliza el evento Eliminación, aquí hay un código (que se corta a lo que es importante):

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);
}
¿Fue útil?

Solución

Tal vez me falta algo, pero ¿por qué añadir nuevos métodos a la API? Cuando se agrega un objeto al contenedor, se podía bruto de colada para comprobar si se trata de IDisposable y manejarlo adecuadamente si es así.

También me pregunto si necesita el destructor. Suponiendo que el contenedor es IDisposable (como el de la Unidad), sólo podría poner en práctica el básico Eliminar el patrón y ahorrar un montón de gastos generales de GC.

Algunas preguntas que pueden ser aplicables:

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top