【发布时间】:2019-10-14 14:59:15
【问题描述】:
我需要解决如何管理在我创建的 DI 容器中注册的相互依赖的实例。
我通过构造函数注入创建了一个简单的 DI 容器,它适用于简单的任务。但是存在一个更大的问题,即当我注册两个实例是相互依赖的(例如,一个类 A 需要一个 B 实例,但 B 需要一个 A 实例),落入 stackoverflow。
public class DIContainer : IContainer
{
private readonly Dictionary<Type, Func<object>> _registeredTypes = new Dictionary<Type, Func<object>>();
public object GetInstance(Type type)
{
if (_registeredTypes.ContainsKey(type))
{
return _registeredTypes[type]();
}
else
{
return null;
}
}
private object CreateInstance(Type type)
{
var constructor = type.GetConstructors()
.OrderByDescending(c => c.GetParameters().Length)
.First();
var args = constructor.GetParameters().Select(p => GetInstance(p.ParameterType)).Where(a => a != null).ToArray();
return Activator.CreateInstance(type, args);
}
public T Get<T>()
{
return (T)GetInstance(typeof(T));
}
public void Register<I, C>()
{
Register(typeof(I), typeof(C));
}
public void RegisterSinglenton<I, C>()
where C : I
{
var instance = CreateInstance(typeof(C));
RegisterSinglenton<I>((C)instance);
}
public void RegisterSinglenton<T>(T obj)
{
_registeredTypes.Add(typeof(T), () => obj);
}
public void Register(Type service, Type implementation)
{
_registeredTypes.Add(service, () => CreateInstance(implementation));
}
}
我知道大多数人会建议使用已经实现的容器(如 ninject 或 autofac),但这是我需要为个人项目实施的解决方案,并且会感谢您可以给我的所有建议.
【问题讨论】:
-
在大多数现代 DI 容器中,循环依赖也会导致抛出异常(当然不是 StackOverflow,但仍然如此)。另一种方法是使用属性注入或注入某种“代理”对象,将未来的调用委托给实际实例。
-
没有可以解决循环依赖的容器,你需要修复你的代码,因为这是不可能的。
-
这不是DI问题,这是代码结构的问题。改一下,注册到 Di 容器的实现不会相互依赖。
标签: c# dependency-injection ioc-container