Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 使用Ninject,如果创建自定义提供程序,我必须确保单个实例,还是可以使用SingleInstance属性?_.net_Unit Testing_Dependency Injection_Ninject - Fatal编程技术网

.net 使用Ninject,如果创建自定义提供程序,我必须确保单个实例,还是可以使用SingleInstance属性?

.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

我希望彼得或鲁本能看到这个问题,因为他们似乎是Ninject的热门人选。我需要创建一个自定义提供程序,因为我有一个接受4个参数的类。这两个参数可以被注入,因为它们是类型,而另外两个是配置参数,是整数。它们指的是以毫秒为单位的超时

[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;
    }
}    
我以前依赖于我创建的工厂来获取超时和延迟的配置设置,并注入一些东西和其他东西。现在看来,要做到这一点,我必须创建自己的自定义提供程序。我同意

额外的几点:

  • 我知道我可以在床上打针 参数。但这造成了 欺骗性的API。对象应该是 以随时可用状态返回,并且 如果没有这4个论点,情况就不是这样了 随时可用
  • 同样的论点也适用 注射法
  • 我最后的问题是:

    • 这是否意味着我可以控制再次确保单个实例,或者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