2

我试图找到一种将构造函数参数传递给子类的构造函数的方法。这些对象是不可变的,所以我更喜欢使用构造函数参数。

我遇到的问题是 ConstructorArgument 不继承到子实例化,并且以下语句不可互换:

_parsingProcessor = _kernel.Get<IParsingProcessor>(new ConstructorArgument("dataFilePath", dataFilePath);

_parsingProcessor = _kernel.Get<IParsingProcessor>(new Parameter("dataFilePath", dataFilePath, true);

那么,如何获得可继承的 ConstructorArgument 以及何时有意义(如果有的话)新建 Parameter 类?

4

1 回答 1

3

是的,你可以这样做,但这可能不是你真正想要的。如果容器实际上不负责实例化它自己的依赖项,那么它的依赖项可能不应该共享它的构造函数参数——它只是没有意义。

我很确定我知道您要做什么,推荐的方法是专门为您的一个容器创建一个唯一的绑定,并使用WhenInjectedInto条件绑定语法,如下例所示:

public class Hello : IHello
{
    private readonly string name;

    public Hello(string name)
    {
        this.name = name;
    }

    public void SayHello()
    {
        Console.WriteLine("Hello, {0}!", name);
    }
}

这是一个接受我们要修改的构造函数参数的类,具体取决于谁要求IHello. 假设这是一个无聊的容器类:

public class MyApp : IApp
{
    private readonly IHello hello;

    public MyApp(IHello hello)
    {
        this.hello = hello;
    }

    public virtual void Run()
    {
        hello.SayHello();
        Console.ReadLine();
    }
}

现在,这里是你如何做绑定:

public class MainModule : NinjectModule
{
    public override void Load()
    {
        Bind<IApp>().To<MyApp>();
        Bind<IHello>().To<Hello>()
            .WithConstructorArgument("name", "Jim");
        Bind<IHello>().To<Hello>()
            .WhenInjectedInto<MyApp>()
            .WithConstructorArgument("name", "Bob");
    }
}

基本上所有这个绑定所做的就是说name应该是“Jim” ,除非它被请求Hello,在这种情况下它是,所以它会得到名称“Bob”。


如果你绝对确定你真的想要级联行为并且理解这是非常危险和脆弱的,你可以使用方法绑定来作弊。假设我们现在为某个未指定的目的name向类添加了一个参数MyApp,绑定将是:

Bind<IHello>().ToMethod(ctx =>
    ctx.Kernel.Get<Hello>(ctx.Request.ParentContext.Parameters
        .OfType<ConstructorArgument>()
        .Where(c => c.Name == "name")
        .First()));

拜托,拜托,在做之前确保你确定是你想要的。它看起来很简单,但在简单的重构过程中也很可能会中断,而且我见过的 95% 的“自定义依赖”场景都可以使用WhenInjectedInto绑定来解决。

于 2011-08-14T21:12:36.473 回答