【问题标题】:Ninject passing in constructor valuesNinject 传入构造函数值
【发布时间】:2011-08-29 06:11:14
【问题描述】:

使用 Ninject,如何配置内核以便我可以定义哪些构造函数值传递到对象的实例化中?

我在一个模块中配置了以下内容:

Bind<IService1>()
    .To<Service1Impl>()
    .InSingletonScope()
    .Named("LIVE");
Bind<IService2>()
    .To<Service2Impl>()
    .InSingletonScope()
    .Named("LIVE")
    .WithConstructorArgument(
        "service1", 
        Kernel.Get<IService1>("LIVE"));

Service2Impl 采用 IService1 的构造函数参数,但我希望它来自容器。我还想命名绑定,因为我的代码将在运行时针对不同的版本。

这似乎可行,但它是实现我想做的正确方法吗? 我是否应该在不使用命名绑定并将不同的配置模块连接到内核的情况下实现?

编辑

我现在使用 ToMethod() 方法来指定一个委托,以便在特定类型的请求时调用。这似乎更好一些,因为如果构造函数配置错误,我将收到编译时警告,而不必知道我首先传递的参数的名称。

谢谢

【问题讨论】:

    标签: c# .net dependency-injection ninject


    【解决方案1】:

    我会推荐 WithConstructorParameter 重载,它需要像这样的 lambda:

    Bind<IService2>()
        .To<Service2Impl>()
        .InSingletonScope()
        .Named("LIVE")
        .WithConstructorArgument(
            "service1", 
            ctx => ctx.Kernel.Get<IService1>("LIVE"));
    

    这将确保IServive1 的解析发生在激活Service2Impl 时,而不是在创建容器时启动。虽然在您的情况下,Service1Impl 是单例并不重要,但按照您最初编写的方式进行操作可能会产生副作用:

    • WithConstructorArgument 注入的依赖绑定必须已经存在。这意味着所有绑定都必须按特定顺序完成。当涉及多个模块时,这会变得很棘手。

    • 使用自定义范围时可能会出现范围问题。 Ninject 2.0 引入了缓存和收集范围管理,绑定到常量很可能会使其陷入混乱。

    【讨论】:

      【解决方案2】:

      最后我使用了 ToMethod,它允许我使用构造函数构造所需的实例,以维护编译时错误。

      例如:

      .ToMethod(Func<IContext, T> method)
      
      Bind<IWeapon>().ToMethod(context => new Sword());
      

      【讨论】:

      • 比起 .WithConstructorArgument 更喜欢这种语法,编译器会捕获重构错误。 +1
      • 你真的有一个应用程序需要一个 Weapon 接口和 Sword 对象吗?
      【解决方案3】:

      看来你看错了。如果 Ninject 将服务 1 作为构造函数参数,它将自动将服务 1 注入服务 2。在这种情况下不需要 WithConstructorArgument。

      如果有多个 IService1 你应该去寻找条件。例如。 WhenParentNamed(...)

      【讨论】:

        【解决方案4】:

        也许提供者可以帮助您。将 IService2 绑定到提供程序。并在Provider的Create方法中,使用Kernel.Get("LIVE")创建Service2Impl实例。

        查看以下链接了解如何使用Provider https://github.com/ninject/ninject/wiki/Providers%2C-Factory-Methods-and-the-Activation-Context

        【讨论】:

        • 谢谢,我看到了。认为代码太多了,正如您共享的链接中所说,ToMethod 是提供程序的精简版本。
        【解决方案5】:

        我认为ToConstant() 更干净,InSingletonScope 是隐含的:

        Bind<IService2>().ToConstant(new Service2Impl(argument)))
                         .Named("LIVE");
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-07
          • 2012-02-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多