Estoy trabajando en mi contenedor DI/IoC OpenNETCF.IoC y tengo una solicitud (razonable) para agregar algún tipo de gestión del ciclo de vida para los artículos IDisposable en las colecciones de contenedores.DI: manejo de la vida de objetos identificables
Mi idea actual es que, como no puedo consultar un objeto para ver si ha sido eliminado, y no puedo obtener un evento para cuando haya sido eliminado, tengo que crear alguna forma de contenedor para los objetos que un desarrollador quiere que se administre el marco.
public TTypeToBuild AddNew<TTypeToBuild>() { ... }
Lo que estoy considerando es la adición de un nuevo método (tambié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)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 elemento se agrega al contenedor mediante AddNewDIsposable, también se agrega un controlador de eventos para que cuando se disipe (a través del contenedor) el marco lo elimine de la colección subyacente.
De hecho, tengo esto implementado y está pasando las pruebas unitarias, pero estoy buscando opiniones sobre dónde podría romperse, o cómo podría hacerse más "amigable" para el desarrollador consumidor.
EDIT 1
Puesto 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);
}
¿Podemos obtener una descripción más completa de la función específica que se agrega? ¿Cuáles son los casos de uso para los que la gente quiere esto, es el controlador de eventos para usted como el (marco IoC) o el usuario final? Etc .. – Quibblesome
El caso de uso es para agregar la administración automática del ciclo de vida. Si agrega un artículo IDisposable a una colección y luego llama a Dispose, en realidad nunca se limpiará porque el contenedor tiene una raíz para el objeto. La idea es que puede llamar a Dispose sobre el objeto sin tener que volver a la colección para encontrarlo, y que eso provoque automáticamente la eliminación de la colección del contenedor. El evento se usa puramente internamente por el marco (incluso se marca como interno para no ser utilizado fuera) y el manejador lo elimina de la colección. – ctacke
He actualizado la pregunta para agregar el manejo del evento para mayor claridad. – ctacke