Ninject传递构造函数值

Tim*_*eel 13 .net c# dependency-injection ninject

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

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

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

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

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

编辑

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

谢谢

Igo*_*aka 18

我会建议WithConstructorParameter像这样采用lambda 的重载:

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

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

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

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


Tim*_*eel 14

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

例如:

.ToMethod(Func<IContext, T> method)

Bind<IWeapon>().ToMethod(context => new Sword());
Run Code Online (Sandbox Code Playgroud)


Rem*_*oor 6

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

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