C# 向单例注入参数
使用Ninject,我有一个接口,我想绑定到具体实现的单个实例。例如:C# 向单例注入参数,c#,ninject,inversion-of-control,C#,Ninject,Inversion Of Control,使用Ninject,我有一个接口,我想绑定到具体实现的单个实例。例如: public interface IFoo { //... } public class Foo { //... } 现在通常,我会像这样绑定一些东西: kernel.Bind<IFoo>().To<Foo>().InSingletonScope(); 现在的问题是,在设置所有绑定时,我无法知道myBar的值。我需要推迟到第一次需要IFoo(注意,实际上我有几个参数要传递)。所以我需要的是一个单例
public interface IFoo { //... }
public class Foo { //... }
现在通常,我会像这样绑定一些东西:
kernel.Bind<IFoo>().To<Foo>().InSingletonScope();
现在的问题是,在设置所有绑定时,我无法知道myBar
的值。我需要推迟到第一次需要IFoo
(注意,实际上我有几个参数要传递)。所以我需要的是一个单例,它在第一次使用时是惰性初始化的,并且在那个时候只获取参数
最好的方法是什么?我假设解决方法可能是使用,但我不太明白正确的方法。我不想每次都创建一个新的
Foo
如我上面的评论所示。真正的问题是,当您需要Foo时,您可能没有构造参数。在此模式中,您可以随意绑定所有接口并调用IIInitializer。准备好后进行初始化(OBV需要保留引用或使其保持静态)
如果在正确设置它之前调用它,Foo将抛出异常
IFoo保持不变
iInitializer实现可以调整为轮询DB或响应事件,或者任何最适合您的后期配置senario的方式
using System;
namespace UnitTestProject3
{
public interface IFoo
{
int GetAllTheFoo();
}
public interface IInitialiser
{
void Initialise(int x);
int GetX();
bool IsReady { get; }
}
public class Foo : IFoo
{
private bool isInitalised;
private int x;
private IInitialiser i;
public Foo(IInitialiser i)
{
this.isInitalised = false;
this.i = i;
}
protected void Init()
{
if (this.isInitalised)
{
return;
}
else if (i.IsReady)
{
x = i.GetX();
this.isInitalised = true;
return;
}
else
{
throw new Exception("you have not set x");
}
}
public int GetAllTheFoo()
{
Init();
return x;
}
}
}
您可以使用工厂扩展
public interface IFooFactory
{
IFoo CreateFoo(string bar);
IFoo CreateFoo();
}
public interface IFoo
{
string Bar { get; set; }
}
public class Foo : IFoo
{
public string Bar { get; set; }
public Foo(string bar)
{
Bar = bar;
}
}
kernel.Bind<IFoo>().To<Foo>().InSingletonScope();
kernel.Bind<IFooFactory>().ToFactory();
IFoo foo1 = fooFactory.CreateFoo("myBar");
IFoo foo2 = fooFactory.CreateFoo("myDifferentBar"); // value is basically ignored here
IFoo foo3 = fooFactory.CreateFoo();
公共接口IFooFactory
{
IFoo CreateFoo(字符串栏);
ifoocreatefoo();
}
公共接口IFoo
{
字符串栏{get;set;}
}
公共类Foo:IFoo
{
公共字符串条{get;set;}
公共Foo(字符串栏)
{
巴=巴;
}
}
kernel.Bind().To().InSingletonScope();
kernel.Bind().ToFactory();
IFoo foo1=foodfactory.CreateFoo(“myBar”);
IFoo foo2=foodfactory.CreateFoo(“myDifferentBar”);//这里基本上忽略了值
IFoo foo3=foodfactory.CreateFoo();
这将始终返回相同的Foo实例。当然,如果你先调用无参数方法,它将导致一个异常。给出另外两个答案,我可能完全没有抓住问题的重点,但为什么像这样简单的事情对你不起作用呢:
kernel.Bind<IFoo>().ToMethod(x => CreateFoo()).InSingletonScope();
kernel.Bind();
CreateFoo
将负责使用所需的任何参数集构造单个对象。调用CreateFoo
时,您应该已经知道参数是什么。您不能在程序中的任何一点绑定吗?@Ewan:不能不传递内核,我不想这样做。除非我遗漏了什么。在我看来,当你谈论DI时,你的问题是“第一次需要IFoo”是不确定的。那么你怎么知道你知道在那一点上的构造参数呢?不,我同意传递内核不是一个好的解决方案。但你有个奇怪的案子我有个更好的。让Foo接受一个IInitializer构造函数。当您调用它的方法时,它会调用initializer来尝试获取所需的参数并初始化它自己。只要这些参数可用,您就可以在初始化器上设置这些参数。这样可以避免在IFoo中添加额外的特定于Foo的内容
kernel.Bind<IFoo>().ToMethod(x => CreateFoo()).InSingletonScope();