Ninject - WithConstructorArgument 的重载行为很奇怪

Ninject - overloads for WithConstructorArgument behave weird

我有以下代码:

namespace Test.Ninject.ConstructorArgumentBug
{

public class ClassA
{
    private readonly IDependecy _dependecy;

    public ClassA(IDependecy dependecy)
    {
        _dependecy = dependecy;
    }
}

public interface IDependecy
{
}

public class ConcreteDependency : IDependecy
{
    private readonly string _arg;

    public ConcreteDependency(string arg)
    {
        _arg = arg;
    }
}

public class Tests
{
    [Test]
    public void Test1()
    {
        var kernel = new StandardKernel();
        kernel.Bind<IDependecy>()
            .To<ConcreteDependency>()
            .WhenInjectedInto<ClassA>()
            .WithConstructorArgument(new ConstructorArgument("arg", "test"));

        var classA = kernel.Get<ClassA>();
        Assert.IsNotNull(classA);
    }

    [Test]
    public void Test2()
    {
        var kernel = new StandardKernel();
        kernel.Bind<IDependecy>()
            .To<ConcreteDependency>()
            .WhenInjectedInto<ClassA>()
            .WithConstructorArgument("arg", "test");

        var classA = kernel.Get<ClassA>();
        Assert.IsNotNull(classA);
    }
}
}

Test1 不起作用,但 Test2 起作用,我相信它们的行为应该相同。对我来说它看起来像一个错误。由于某种原因,第一个测试无法解决依赖关系,并出现以下错误:

Ninject.ActivationException : Error activating string No matching bindings are available, and the type is not self-bindable. Activation path: 3) Injection of dependency string into parameter arg of constructor of type ConcreteDependency 2) Injection of dependency IDependecy into parameter dependecy of constructor of type ClassA 1) Request for ClassA

我想如果第一个测试失败,第二个测试也应该失败。我做错了什么吗?

谢谢!

Test1 中,您正在调用的 WithConstructorArgument 方法具有以下签名:

IBindingWithOrOnSyntax<T> WithConstructorArgument<TValue>(TValue value);

以下是文档中关于此方法的内容(您可以在 IntelliSense 上获得):

Indicates that the specified constructor argument should be overridden with the specified value.

这里是 TValue 的文档:

Specifies the argument type to override

这里是 value 的文档:

The value for the argument

所以,这一行:

.WithConstructorArgument(new ConstructorArgument("arg", "test"));

相当于(C# 自动推断 TValue):

.WithConstructorArgument<ConstructorArgument>(new ConstructorArgument("arg", "test"));

告诉 NInject ConcreteDependency 的构造函数有一个 ConstructorArgument 类型的参数,而实际上它有一个 string.[=34 类型的参数=]

所以你应该把它改成

.WithConstructorArgument<string>("test");

或更简单:

.WithConstructorArgument("test");

请注意,没有 WithConstructorArgument 的重载具有 ConstructorArgument.

类型的参数

然而,还有另一种名为 WithParameter 的方法接受 IParameter.

由于 ConstructorArgument 实现了 IParameter,您可以使用此方法通过 ConstructorArgument 指定构造函数参数,如下所示:

kernel.Bind<IDependecy>()
    .To<ConcreteDependency>()
    .WhenInjectedInto<ClassA>()
    .WithParameter(new ConstructorArgument("arg", "test"));