Ninject - WithConstructorArgument的重载表现得很奇怪

时间:2015-12-08 17:25:15

标签: c# dependency-injection ninject

我有以下代码:

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:激活字符串时出错   没有匹配的绑定可用,并且该类型不可自绑定。   激活路径:     3)将依赖字符串注入到ConcreteDependency类型的构造函数的参数arg中     2)将依赖IDependecy注入到ClassA类型的构造函数的参数依赖性中     1)申请ClassA

我想如果第一次测试失败,第二次测试也会失败。我做错了吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

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

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

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

  

表示应使用指定的值覆盖指定的构造函数参数。

以下是TValue的文档:

  

指定要覆盖的参数类型

以下是value的文档:

  

参数的值

所以,这一行:

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

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

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

告诉NInject ConcreteDependency的构造函数的参数类型为ConstructorArgument,实际上它的参数类型为string

所以你应该把它改成

.WithConstructorArgument<string>("test");

或更简单:

.WithConstructorArgument("test");

请注意,WithConstructorArgument没有超载的参数类型为ConstructorArgument

但是,另一种名为WithParameter的方法会引入IParameter

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

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