Ninject传递构造函数值

时间:2011-05-19 22:18:37

标签: c# .net dependency-injection ninject

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

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

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

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

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

修改

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

由于

5 个答案:

答案 0 :(得分:16)

我建议WithConstructorParameter重载采用lambda,如下所示:

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

这将确保IServive1的分辨率在激活Service2Impl时发生,而不是在创建容器时启动时发生。虽然在你的情况下并不重要,因为Service1Impl是单身,但是按照你最初编写它的方式可能会产生副作用:

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

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

答案 1 :(得分:13)

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

例如:

.ToMethod(Func<IContext, T> method)

Bind<IWeapon>().ToMethod(context => new Sword());

答案 2 :(得分:6)

看来你正在以错误的方式看待这个问题。如果将服务1作为构造函数参数,则Ninject会自动将服务1注入服务2。在这种情况下,不需要WithConstructorArgument。

如果有多个IService1,你应该选择条件。例如。 WhenParentNamed(...)

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

我认为ToConstant()更清晰,InSingletonScope是隐含的:

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