为什么我不能用Ninjects ConstructorArgument注入值null?

时间:2010-04-19 12:14:48

标签: .net ioc-container ninject ninject-2 constructorargument

使用Ninjects ConstructorArgument时,您可以指定要注入特定参数的确切值。为什么这个值不能为null,或者我怎样才能使它工作?也许这不是你想做的事情,但我想在我的单元测试中使用它。例如:

public class Ninja
{
    private readonly IWeapon _weapon;
    public Ninja(IWeapon weapon)
    {
        _weapon = weapon;
    }
}

public void SomeFunction()
{
    var kernel = new StandardKernel();
    var ninja = kernel.Get<Ninja>(new ConstructorArgument("weapon", null));
}

4 个答案:

答案 0 :(得分:7)

查看源代码(以及通过重新定义得到的堆栈跟踪,您省略了:P)

这是因为它绑定到ConstructorArgument ctor的不同重载而不是正常用法(即,您传递的是Value Type或非null引用类型)。

解决方法是将null转换为Object: -

var ninja = kernel.Get<Ninja>( new ConstructorArgument( "weapon", (object)null ) );

Ninject 2来源:

public class ConstructorArgument : Parameter
{
    /// <summary>
    /// Initializes a new instance of the <see cref="ConstructorArgument"/> class.
    /// </summary>
    /// <param name="name">The name of the argument to override.</param>
    /// <param name="value">The value to inject into the property.</param>
    public ConstructorArgument(string name, object value) : base(name, value, false) { }

    /// <summary>
    /// Initializes a new instance of the <see cref="ConstructorArgument"/> class.
    /// </summary>
    /// <param name="name">The name of the argument to override.</param>
    /// <param name="valueCallback">The callback to invoke to get the value that should be injected.</param>
    public ConstructorArgument(string name, Func<IContext, object> valueCallback) : base(name, valueCallback, false) { }
}

摄制:

public class ReproAndResolution
{
    public interface IWeapon
    {
    }

    public class Ninja
    {
        private readonly IWeapon _weapon;
        public Ninja( IWeapon weapon )
        {
            _weapon = weapon;
        }
    }

    [Fact]
    public void TestMethod()
    {
        var kernel = new StandardKernel();
        var ninja = kernel.Get<Ninja>( new ConstructorArgument( "weapon", (object)null ) );
    }
}

课?你不要下载最新的资源并查看它。很棒的评论,干净的代码库。再次感谢@Ian Davis的提示/刺激!

答案 1 :(得分:3)

我不知道Ninject,但是AFAIK构造函数注入通常用于强制依赖,因此null在这种情况下没有多大意义。如果依赖项不是必需的,则类型应提供默认构造函数并使用属性注入。

This post提供了其他信息。

答案 2 :(得分:3)

  

我想在单元测试中使用它

no need to use an IOC container for unit tests。您应该使用容器在运行时将应用程序连接在一起,仅此而已。如果这开始受到伤害,它的气味就表明你的课程已经失控(SRP违规?)

您的单元测试将在此示例中:

var ninja = new Ninja(null);

以上是合法的C#代码,并且为单元测试传递空引用是一种完全有效的单元测试区域,不需要依赖。

答案 3 :(得分:0)

这可能不受支持,因为构造函数参数也可以是值类型。