注入带参数的单例
Inject a singleton with parameters
使用 Ninject,我有一个接口,我想绑定到具体实现的单个实例。例如:
public interface IFoo { //... }
public class Foo { //... }
现在通常,我会像这样绑定这样的东西:
kernel.Bind<IFoo>().To<Foo>().InSingletonScope();
但是,我需要向 Foo
的构造函数添加参数。通常,这也不是什么大问题(我认为):
kernel.Bind<IFoo>()
.To<Foo>()
.InSingletonScope()
.WithConstructorArgument("bar", myBar);
现在的问题是我在设置所有绑定时无法知道 myBar
的值。我需要将它推迟到我第一次需要 IFoo
时(注意,实际上我有几个参数要通过)。所以我需要的是一个单例,它将在第一次使用时进行延迟初始化,并且只在那时获取参数。
解决这个问题的最佳方法是什么?我假设 Factory 可能是解决方案,但我不太清楚执行此操作的正确方法。我不想每次都创建一个 new Foo
。
正如我上面的评论。真正的问题是,当你需要 Foo 时,你可能没有构造参数。在此模式中,您可以随意绑定所有接口,并在准备就绪时调用 IInitialiser.Initialise(您需要保留引用或使其成为静态)。
如果在正确设置之前调用 Foo,它会抛出异常
IFoo保持不变
可以调整 IInitialiser 实现以轮询数据库或响应事件或任何最适合您的后期配置的方案
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;
}
}
}
您可以使用 Factory 扩展。
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();
这将始终return Foo 的同一个实例。当然如果先调用无参方法会抛出异常
鉴于其他两个答案,我可能完全忽略了问题的重点,但为什么像这个简单的东西对你不起作用:
kernel.Bind<IFoo>().ToMethod(x => CreateFoo()).InSingletonScope();
CreateFoo
将负责使用您需要的任何参数集构建您的单个对象。在调用 CreateFoo
时,您应该已经知道参数是什么了。
使用 Ninject,我有一个接口,我想绑定到具体实现的单个实例。例如:
public interface IFoo { //... }
public class Foo { //... }
现在通常,我会像这样绑定这样的东西:
kernel.Bind<IFoo>().To<Foo>().InSingletonScope();
但是,我需要向 Foo
的构造函数添加参数。通常,这也不是什么大问题(我认为):
kernel.Bind<IFoo>()
.To<Foo>()
.InSingletonScope()
.WithConstructorArgument("bar", myBar);
现在的问题是我在设置所有绑定时无法知道 myBar
的值。我需要将它推迟到我第一次需要 IFoo
时(注意,实际上我有几个参数要通过)。所以我需要的是一个单例,它将在第一次使用时进行延迟初始化,并且只在那时获取参数。
解决这个问题的最佳方法是什么?我假设 Factory 可能是解决方案,但我不太清楚执行此操作的正确方法。我不想每次都创建一个 new Foo
。
正如我上面的评论。真正的问题是,当你需要 Foo 时,你可能没有构造参数。在此模式中,您可以随意绑定所有接口,并在准备就绪时调用 IInitialiser.Initialise(您需要保留引用或使其成为静态)。
如果在正确设置之前调用 Foo,它会抛出异常
IFoo保持不变
可以调整 IInitialiser 实现以轮询数据库或响应事件或任何最适合您的后期配置的方案
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;
}
}
}
您可以使用 Factory 扩展。
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();
这将始终return Foo 的同一个实例。当然如果先调用无参方法会抛出异常
鉴于其他两个答案,我可能完全忽略了问题的重点,但为什么像这个简单的东西对你不起作用:
kernel.Bind<IFoo>().ToMethod(x => CreateFoo()).InSingletonScope();
CreateFoo
将负责使用您需要的任何参数集构建您的单个对象。在调用 CreateFoo
时,您应该已经知道参数是什么了。