Esto también me ha dejado perplejo. Aunque no estoy contento con eso, siempre llegué a la conclusión de que nunca mejor devolver un objeto IDisposable de forma transitoria.
Recientemente, reformulé la pregunta para mí: ¿Esto realmente es un problema de IoC, o un problema de .NET Framework? La eliminación es incómoda de todos modos. No tiene un propósito funcional significativo, solo técnico. Entonces, es más un problema de marco con el que tenemos que lidiar, que un problema de IoC.
Lo que me gusta de DI es que puedo solicitar un contrato dándome la funcionalidad, sin tener que preocuparme por los detalles técnicos. No soy el dueño. Sin conocimiento sobre la capa en la que se encuentra. Sin conocimiento sobre qué tecnologías se requieren para cumplir con el contrato, no se preocupe por la duración. Mi código se ve bien y limpio, y es altamente comprobable. Puedo implementar responsabilidades en las capas a las que pertenecen.
De modo que si hay una excepción a esta regla que me exige organizar la duración, hagamos esa excepción. Si me gusta o no. Si el objeto que implementa la interfaz me obliga a desecharlo, quiero saberlo, ya que desde entonces me activé para usar el objeto lo más breve posible. Un truco al resolverlo usando un contenedor para niños que se desecha un tiempo más tarde todavía podría causarme mantener el objeto con vida por más tiempo del que debería. La vida útil permitida del objeto se determina al registrar el objeto. No por la funcionalidad que crea un contenedor hijo y se aferra a eso durante un cierto período.
De modo que mientras los desarrolladores tengamos que preocuparnos por la eliminación (¿cambiará alguna vez?) Intentaré inyectar el menor número posible de objetos desechables transitorios. 1. Intento que el objeto no sea identificable, por ejemplo, al no mantener los objetos desechables en el nivel de clase, pero en un ámbito más pequeño. 2. Intento que el objeto sea reutilizable para que se pueda aplicar un administrador de vida diferente.
Si esto no es posible, utilizo una fábrica para indicar que el usuario del contrato inyectado es el propietario y debe asumir la responsabilidad por ello.
Hay una advertencia: cambiar un implementador de contrato de no desechable a desechable será un cambio radical. En ese momento, la interfaz ya no estará registrada, sino la interfaz de fábrica.Pero creo que esto se aplica también a otros escenarios. Olvidarse de usar un contenedor para niños dará problemas de memoria a partir de ese momento. El enfoque de fábrica provocará una excepción de resolución de IoC.
un código de ejemplo:
using System;
using Microsoft.Practices.Unity;
namespace Test
{
// Unity configuration
public class ConfigurationExtension : UnityContainerExtension
{
protected override void Initialize()
{
// Container.RegisterType<IDataService, DataService>(); Use factory instead
Container.RegisterType<IInjectionFactory<IDataService>, InjectionFactory<IDataService, DataService>>();
}
}
#region General utility layer
public interface IInjectionFactory<out T>
where T : class
{
T Create();
}
public class InjectionFactory<T2, T1> : IInjectionFactory<T2>
where T1 : T2
where T2 : class
{
private readonly IUnityContainer _iocContainer;
public InjectionFactory(IUnityContainer iocContainer)
{
_iocContainer = iocContainer;
}
public T2 Create()
{
return _iocContainer.Resolve<T1>();
}
}
#endregion
#region data layer
public class DataService : IDataService, IDisposable
{
public object LoadData()
{
return "Test data";
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
/* Dispose stuff */
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
#endregion
#region domain layer
public interface IDataService
{
object LoadData();
}
public class DomainService
{
private readonly IInjectionFactory<IDataService> _dataServiceFactory;
public DomainService(IInjectionFactory<IDataService> dataServiceFactory)
{
_dataServiceFactory = dataServiceFactory;
}
public object GetData()
{
var dataService = _dataServiceFactory.Create();
try
{
return dataService.LoadData();
}
finally
{
var disposableDataService = dataService as IDisposable;
if (disposableDataService != null)
{
disposableDataService.Dispose();
}
}
}
}
#endregion
}
Mi solución es utilizar un IoC con una gestión adecuada y bien codificado-vida: autofac y el castillo de Windsor tiene tal (aunque trabajan de forma ligeramente diferente); La Unidad 2.1 simplemente falla cuando se trata de transitorios bajo los administradores de por vida predeterminados. – user2864740