我有一个类(MyFacade
)我用Ninject
注入了参数:
class MyFacade
{
IDemoInterface demo;
public MyFacade(IDemoInterface demo)
{
this.demo = demo;
}
public void MyMethod()
{
Console.WriteLine(demo.GetInfo());
}
}
当然,我必须设置Ninject
以注入适当的参数实现(IDemoInterface
)
我知道,我可以通过MyFacade
实例化kernel.Get<MyFacade>();
对象而不设置任何其他内容。目前我的门面没有接口(因为它是我唯一的实现,也许我会为标准建议添加其接口)
如果我想制作这个外观singlenton,我知道两种方法:创建一个空构造函数并通过执行此kernel.Get<IDemoInterface>();
或通过设置Ninject传递参数:kernel.Bind<MyFacade>().To<MyFacade>().InSingletonScope();
第二个看起来更好的方法,但你知道以单一方式设置它的任何其他方法吗?
答案 0 :(得分:25)
设置绑定时,需要绑定依赖项。在绑定中设置依赖项总是更好,而不是在构造函数中执行kernel.Get<T>()
。您正在使用IOC,因此请利用您正在使用的框架为您进行注射。
在第二个示例绑定中,您缺少的是IDemoInterface
中的绑定。您的绑定应如下所示:
//bind the dependency to the implementation.
kernel.Bind<IDemoInterface>().To<DemoInterface>();
//since you bound your dependency, ninject should now have
// all the dependencies required to instantiate your `MyFacade` object.
kernel.Bind<MyFacade>.To<MyFacade>().InSingletonScope();
答案 1 :(得分:5)
如果您不希望容器使用InSingletonScope()
管理单件的生命周期,但仍希望它被注入,我可以想到两种方法。选择哪一种更适合您的需求。请考虑以下ISingleton
(命名您的界面)实现:
public class ConcreteSingleton : ISingleton
{
private static readonly Lazy<ConcreteSingleton> _instance = new Lazy<ConcreteSingleton>(() => new ConcreteSingleton());
private ConcreteSingleton() { }
public static ConcreteSingleton Instance
{
get
{
return _instance.Value;
}
}
}
改变单身人士课程 GetInstance(...)
方法
在这种方法(我的首选方法)中,您不会每次都调用kernel.Inject(instance)
,而只是第一次初始化单例。将以下方法添加到ConcreteSingleton
类:
public static ConcreteSingleton GetInstance(IKernel kernelForInjection)
{
if (_instance.IsValueCreated == false)
{
kernelForInjection.Inject(_instance.Value);
}
return _instance.Value;
}
并使用此绑定:
kernel.Bind<ISingleton>().ToMethod(c => ConcreteSingleton.GetInstance(c.Kernel));
将实现没有公共构造函数但是能够有效注入外观的所需行为。
每次请求 ISingleton
实例时执行注入
如果由于任何原因您不允许修改您的ConcreteSingleton
:此方法将单例创建包装在提供程序中,以便仅在第一次创建实例时有效地注入实例。重要的是要注意提供者本身必须注册为单身人士。
internal class ConcreteSingletonProvider : Provider<ISingleton>
{
public IKernel Kernel { get; set; }
//Just a wrapper
private readonly Lazy<ISingleton> _lazy = new Lazy<ISingleton>(() => ConcreteSingleton.Instance);
public ConcreteSingletonProvider(IKernel kernel)
{
Kernel = kernel;
}
protected override ISingleton CreateInstance(IContext context)
{
if (_lazy.IsValueCreated == false)
{
Kernel.Inject(ConcreteSingleton.Instance);
}
return _lazy.Value;
}
}
你的绑定应该是这样的:
kernel.Bind<ISingleton>().ToProvider<ConcreteSingletonProvider>();
kernel.Bind<ConcreteSingletonProvider>().ToSelf().InSingletonScope();
此gist为上述方法提供了完整的工作样本。
希望有所帮助!