5

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

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

4 回答 4

7

查看源代码(以及我通过复制获得的堆栈跟踪,您省略了:P)

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

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

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

忍者 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 的提示/刺激!

于 2010-04-19T12:59:16.650 回答
3

我想在我的单元测试中使用它

无需使用 IOC 容器进行单元测试。您应该使用容器在运行时将您的应用程序连接在一起,仅此而已。如果这开始受到伤害,它的气味表明你的班级正在失控(违反 SRP?)

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

var ninja = new Ninja(null);

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

于 2010-04-19T13:03:59.850 回答
3

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

这篇文章提供了额外的信息。

于 2010-04-19T12:41:45.803 回答
0

This is probably unsupported because constructor arguments can be value types too.

于 2010-04-19T12:27:03.483 回答