我终于开始理解C#中的IoC和DI,但是有些地方仍然让我感到困惑。我正在使用Unity容器,但我认为这个问题更广泛适用。
使用IoC容器来分发实现IDisposable接口的实例让我很不安!你如何知道是否应该Dispose()它?这个实例可能只是专门为你创建的(因此你应该Dispose()),或者它可能是由其他地方管理生存期的实例(因此你最好不要)。代码中没有任何提示,实际上这可能会根据配置而改变!这对我来说看起来很危险。
在场的任何IoC专家能描述一下处理这种模糊性的好方法吗?
我终于开始理解C#中的IoC和DI,但是有些地方仍然让我感到困惑。我正在使用Unity容器,但我认为这个问题更广泛适用。
使用IoC容器来分发实现IDisposable接口的实例让我很不安!你如何知道是否应该Dispose()它?这个实例可能只是专门为你创建的(因此你应该Dispose()),或者它可能是由其他地方管理生存期的实例(因此你最好不要)。代码中没有任何提示,实际上这可能会根据配置而改变!这对我来说看起来很危险。
在场的任何IoC专家能描述一下处理这种模糊性的好方法吗?
绝对不应该在注入到你的类中的对象上调用Dispose()。你不能假设只有你是唯一的使用者。最好的方法是在某个托管接口中包装你的非托管对象:
public class ManagedFileReader : IManagedFileReader
{
public string Read(string path)
{
using (StreamReader reader = File.OpenRead(path))
{
return reader.ReadToEnd();
}
}
}
那只是一个例子,如果我想把文本文件读入字符串中,我会使用File.ReadAllText(path)。
另一种方法是注入一个工厂并自行管理对象:
public void DoSomething()
{
using (var resourceThatShouldBeDisposed = injectedFactory.CreateResource())
{
// do something
}
}
container.Release
方法。 - Krzysztof Kozmicusing 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
}
我认为通常最好的方法是不要Dispose已经注入的东西;你必须假设注入器正在进行分配和释放。