【发布时间】:2013-03-04 12:32:38
【问题描述】:
我正在尝试使用 NInject 解析已知的 Foo 服务固定列表(在单例范围内);此解决方案发生在 FooProvider 的构造函数中。问题是每个 Foo 也需要这个提供者。
public interface IFoo { }
public interface IFooProvider { }
public class Foo : IFoo
{
private readonly IFooProvider _provider;
public Foo(IFooProvider provider)
{
_provider = provider;
}
}
public class FooProvider : IFooProvider
{
private List<IFoo> _allFooServices;
public FooProvider(IKernel kernel)
{
_allFooServices = kernel.GetAll<IFoo>().ToList();
}
}
public class Program
{
private static void Main(string[] args)
{
var IoC = new StandardKernel();
IoC.Bind<IFoo>().To<Foo>().InSingletonScope();
IoC.Bind<IFooProvider>().To<FooProvider>().InSingletonScope();
var foo = IoC.Get<IFoo>();
}
}
这里有一个逻辑循环,显然堆栈溢出表明它正在下降。但是,我将两个接口都绑定到单例。
考虑一下;我们尝试解析 IFoo,然后需要解析 IFooProvider,它本身需要一个 IFoo 列表……但我们还没有解析任何 IFoo 单例,因为我们仍在尝试解决它!
那么我该如何解决这个问题?
[编辑] 可能的解决方案; IFoo 服务实例的延迟缓冲。
public FooProvider(IKernel kernel)
{
_kernel = kernel;
}
public IFoo Find(object context)
{
if (_allFooServices == null)
_allFooServices = _kernel.GetAll<IFoo>().ToList();
return _allFooServices.Where(...
[为什么?]
一般的想法是避免服务定位器模式,因为我已经看到它被描述为一种反模式。因此,与其在运行时尝试通过依赖注入器解析服务;您尝试在设置过程中获取服务列表。但是,这样做的问题是,如果您的任何服务想要找到其他服务,您就会遇到上述问题。
【问题讨论】:
-
那么为什么
Foo需要FooProvider的实例?如果事实上FooProvider是一个创建Foo的工厂,那么它应该可以通过其他方式轻松获得是吗? -
所有 Foo 都是服务,FooProvider 试图在注入时获取所有 Foo 服务的(已解析)列表。如果任何 foo 需要在运行时找到另一个 foo(特定于上下文),它可以在运行时询问 FooProvider。
-
那么
FooProvider不应该是一个可以通过所有其他Foo的依赖注入轻松解决的单例吗? -
它们被绑定为单例。
-
那么如果
FooProvider已经被绑定为一个单例,如果你需要一个作为Foo只需使用依赖注入来恢复它。真的应该这么简单。
标签: c# dependency-injection ninject stack-overflow