.net 使用Ninject,如果创建自定义提供程序,我必须确保单个实例,还是可以使用SingleInstance属性?
我希望彼得或鲁本能看到这个问题,因为他们似乎是Ninject的热门人选。我需要创建一个自定义提供程序,因为我有一个接受4个参数的类。这两个参数可以被注入,因为它们是类型,而另外两个是配置参数,是整数。它们指的是以毫秒为单位的超时.net 使用Ninject,如果创建自定义提供程序,我必须确保单个实例,还是可以使用SingleInstance属性?,.net,unit-testing,dependency-injection,ninject,.net,Unit Testing,Dependency Injection,Ninject,我希望彼得或鲁本能看到这个问题,因为他们似乎是Ninject的热门人选。我需要创建一个自定义提供程序,因为我有一个接受4个参数的类。这两个参数可以被注入,因为它们是类型,而另外两个是配置参数,是整数。它们指的是以毫秒为单位的超时 [SingleInstance] MyClass { ISomething something; IOther other; int timeout; int delay; [Inject] MyClass(ISomet
[SingleInstance]
MyClass
{
ISomething something;
IOther other;
int timeout;
int delay;
[Inject]
MyClass(ISomething something, IOther other, int timeout, int delay)
{
this.something = something;
this.other = other;
this.timeout = timeout;
this.delay = delay;
}
}
我以前依赖于我创建的工厂来获取超时和延迟的配置设置,并注入一些东西和其他东西。现在看来,要做到这一点,我必须创建自己的自定义提供程序。我同意
额外的几点:
- 这是否意味着我可以控制再次确保单个实例,或者Ninject仍然会通过[SingleInstance]属性处理它
- 我不应该回到我的工厂吗?在这种情况下使用Ninject有什么好处
class MyClassProvider : SimpleProvider<MyClass> {
protected override MyClass CreateInstance(IContext context) {
int timeout= ConfigurationManager.AppSettings.Get("timeout");
int delay= ConfiguraionManager.AppSettings.Get("delay");
ISomething something = new SomethingImpl();
IOther other = new OtherImpl();
MyClass newOne = New MyClass(something, other, timeout, delay);
}
}
public class MyModule : StandardModule {
public override void Load() {
Bind<IMyClass>()
.ToProvider<MyClassProvider>()
.Using<SingletonBehavior>();
}
}
类MyClassProvider:SimpleProvider{
受保护的重写MyClass CreateInstance(IContext上下文){
int timeout=ConfigurationManager.AppSettings.Get(“超时”);
int delay=configurationmanager.AppSettings.Get(“延迟”);
ISomething something=新事物impl();
IOther other=新的OtherImpl();
MyClass newOne=新的MyClass(某物、其他、超时、延迟);
}
}
但由于我现在使用的是提供程序,因此绕过了ninject的机制,确保只创建一个对象实例,因此我必须依靠:
class MyClassProvider : SimpleProvider<MyClass> {
protected static readonly MyClass myClassInstance;
private static object locker = new object();
protected override MyClass CreateInstance(IContext context) {
if (myClassInstance == null)
{
lock (locker)
{
int timeout = ConfigurationManager.AppSettings.Get("timeout");
int delay = ConfiguraionManager.AppSettings.Get("delay ");
ISomething something = new SomethingImpl();
IOther other = new OtherImpl();
MyClass newOne = New MyClass(something, other, timeout, delay );
}
return MyClassInstance
}
return myClassInstance
}
}
类MyClassProvider:SimpleProvider{
受保护的静态只读MyClass myClassInstance;
私有静态对象锁定器=新对象();
受保护的重写MyClass CreateInstance(IContext上下文){
if(myClassInstance==null)
{
锁(储物柜)
{
int timeout=ConfigurationManager.AppSettings.Get(“超时”);
int delay=configurationmanager.AppSettings.Get(“延迟”);
ISomething something=新事物impl();
IOther other=新的OtherImpl();
MyClass newOne=新的MyClass(某物、其他、超时、延迟);
}
返回MyClassInstance
}
返回myClassInstance
}
}
有什么我遗漏的吗?老实说,我在理解你的问题时遇到了困难-也许你创建它的代码示例可能会有所帮助(不过你的问题通常措词很好)。但这里有一个刺 不确定您所说的
单实例是什么意思-它来自哪里?(我实际上不知道v1中的SingletonAttribute
,但看到它不在2.0内核中)。虽然它在某些场景中是有意义的,但我绝对不会在类上使用行为属性作为默认方法(即,将其放在绑定定义中)
我仍然会尝试使用一个提供程序(或一个带有lambda的Bind.to*
重载,作为用更少的代码编写工厂的一种方式),特别是当实例化行为层可以在它上面使用时,您将以同样的方式来寻找所有对象,这是一件好事
我要提出的另一个建议是,您的秃顶超时和延迟参数可能会成为DI树的一级公民,例如,IConnectivityPolicy
可以跨多个类使用。你们在这里进行了很好的对话,但我想我应该在原来的问题的基础上添加一个答案来帮助澄清问题
简而言之,如果您在binding语句中指定,Ninject仍将确保您拥有一个对象实例,不管激活机制是什么——也就是说,在使用自己的提供程序时,使用.ToProvider
语法或.ToMethod
语法,不要绕过Ninject确保只创建对象的单个实例的机制
您只需编写提供程序来提供对象实例——提供程序上不强制使用其他语义。因此,创建上面示例中提供的单例实例所需的所有典型goo都不是必需的
例如,您的提供商变得简单得多;尽管如此,我还是在原始示例中添加了使用Ninject内核解析ISomething
和IOther
:
class MyClassProvider : SimpleProvider<MyClass> {
protected override MyClass CreateInstance(IContext context) {
int timeout = ConfigurationManager.AppSettings.Get("timeout");
int delay = ConfiguraionManager.AppSettings.Get("delay ");
ISomething something = context.Kernel.Get<ISomething>();
IOther other = context.Kernel.Get<IOther>();
return new MyClass(something, other, timeout, delay );
}
}
类MyClassProvider:SimpleProvider{
受保护的重写MyClass CreateInstance(IContext上下文){
int timeout=ConfigurationManager.AppSettings.Get(“超时”);
int delay=configurationmanager.AppSettings.Get(“延迟”);
ISomething something=context.Kernel.Get();
IOther other=context.Kernel.Get();
返回新的MyClass(something、other、timeout、delay);
}
}
Ninject模块中的绑定语句如下所示:
class MyClassProvider : SimpleProvider<MyClass> {
protected override MyClass CreateInstance(IContext context) {
int timeout= ConfigurationManager.AppSettings.Get("timeout");
int delay= ConfiguraionManager.AppSettings.Get("delay");
ISomething something = new SomethingImpl();
IOther other = new OtherImpl();
MyClass newOne = New MyClass(something, other, timeout, delay);
}
}
public class MyModule : StandardModule {
public override void Load() {
Bind<IMyClass>()
.ToProvider<MyClassProvider>()
.Using<SingletonBehavior>();
}
}
公共类MyModule:StandardModule{
公共覆盖无效负载(){
绑定()
.ToProvider()
.使用();
}
}
通过使用SingletonBehavior
Ninject,即使您使用自己的提供程序,它仍然只会给您一个MyClass实例
这很容易测试。您可以向类中添加DateTime属性,将其设置为DateTime。现在在构造函数中检查多个调用返回的对象以获取()--即使您在提供程序中创建了该类,它们都将具有相同的时间。接下来,将Using
更改为Using
并