注入传入构造函数值

本文关键字:构造函数 注入 | 更新日期: 2023-09-27 17:57:06

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

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

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

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

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

编辑

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

谢谢

注入传入构造函数值

我会推荐像这样接受lambda的WithConstructorParameter重载:

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

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

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

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

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

例如:

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

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

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

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

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

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

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