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

标签 .net unit-testing dependency-injection ninject

我希望 Peter 或 Ruben 看到这个问题,因为他们似乎是关于 Ninject 的人。我需要创建一个自定义提供程序,因为我有一个需要 4 个参数的类。这两个可以被注入(inject),因为它们是类型,但另外两个是配置参数并且是整数。它们指的是以毫秒为单位的超时。

[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;
    }
}    

我以前依靠我创建的工厂来获取超时和延迟的配置设置,并注入(inject)一些东西和其他东西。现在看来,我必须创建自己的自定义提供程序。我同意。

几点加分:
  • 我知道我可以在
    参数。但这创造了一个
    欺骗性的 API。对象应该是
    以准备使用状态返回,并且
    没有这 4 个论点,它不是
    可以使用。
  • 同样的论点适用
    方法注入(inject)。

  • 所以,我最后的问题:
  • 这是否意味着我可以再次控制单个实例,或者 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);
        }
    }
    

    但是因为我现在使用的是提供程序,所以它会绕过 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
        }
    }
    

    有什么我想念的吗?

    最佳答案

    你们在这里进行了很好的对话,但我想我会根据原始问题添加一个答案来帮助澄清事情。

    简短的回答是,如果您指定 .Using<SingletonBehavior>,Ninject 仍将确保您拥有一个对象的单个实例。在您的绑定(bind)语句中,无论激活机制如何 - 即您不会绕过 Ninject 的机制,即当使用您自己的提供程序时,您不会绕过 Ninject 确保仅创建一个对象实例的机制 .ToProvider语法 -- 或 .ToMethod语法。

    你应该简单地编写你的提供者来提供对象实例——没有其他语义被强加给提供者。因此,不需要您在上面的示例中提供的创建单例实例所需的所有典型 goo。

    例如,您的提供者变得更加简单;虽然,我添加了解决 ISomethingIOther在原始示例中使用 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 = context.Kernel.Get<ISomething>();
        IOther other = context.Kernel.Get<IOther>();
        return new MyClass(something, other, timeout, delay );
      }
    }
    

    Ninject 模块中的绑定(bind)语句如下所示:
    public class MyModule : StandardModule {
      public override void Load() {
    
        Bind<IMyClass>()
          .ToProvider<MyClassProvider>()
          .Using<SingletonBehavior>();
      }
    }
    

    通过使用 SingletonBehavior即使您使用自己的提供程序,Ninject 仍然只会给您一个 MyClass 实例。

    这很容易测试。您可以将 DateTime 属性添加到您的类中,将其设置为 DateTime.Now在构造函数中检查多次调用 Get() 返回的对象——即使您在提供程序中创建了类,它们都将具有相同的时间。接下来,更改 Using<SingletonBehavior>Using<TransientBehavior>并观察差异。您每次都会得到一个新的,全部由您的提供商创建。

    希望这能有所帮助——顺便说一句,我不确定我是不是你所说的彼得,但如果是这样,我很受宠若惊!

    关于.net - 使用 Ninject,如果我创建自定义提供程序,我必须确保单个实例还是可以使用 SingleInstance 属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2325069/

    相关文章:

    c# - MSTest 拒绝运行 64 位?

    java - 使用 Toothpick DI 框架与 Java(仅限)项目一起使用

    dependency-injection - 依赖注入(inject)上下文中的组合根是什么?

    .net - 为什么我不能这样做 - 创建一个 .net 对象并在一行上调用一个方法

    asp.net - DOCTYPE 解析和 ASP.Net 的问题

    .net - 使用 Entity Framework 代码优先我是否需要拥有我的域贫血模型?

    c# - 使用 Moq 模拟 ControllerBase 请求

    java - 如何使用 PowerMockito 在静态方法中模拟新类实例

    javascript - 如何使用 casperjs 显示每次测试的时间

    c# - 注入(inject)包含接口(interface)的所有已注册实现的可枚举