Почему я не могу ввести пустой указатель значения с Ninjects ConstructorArgument?

При использовании 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));
}
5
задан Ruben Bartelink 19 April 2010 в 12:59
поделиться

4 ответа

Глядя на источник (и трассировку стека, которую я получил при повторном воспроизведении, которую вы пропустили: P)

Это связано с тем, что он привязан к другой перегрузке ConstructorArgument ctor, чем при обычном использовании (то есть, когда вы передаете тип значения или ненулевой ссылочный тип).

Обходной путь заключается в приведении значения null к объекту: -

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 за этот совет / подсказку!

7
ответ дан 18 December 2019 в 14:43
поделиться

Вероятно, это не поддерживается, поскольку аргументы конструктора также могут быть типами значений.

0
ответ дан 18 December 2019 в 14:43
поделиться

Я хочу использовать его в своих модульных тестах

Нет необходимости использовать контейнер IOC для модульных тестов . Вы должны использовать контейнер, чтобы связать ваше приложение во время выполнения, и не более того. И если это начинает причинять боль, это запах, указывающий на то, что ваш класс выходит из-под контроля (нарушение SRP?)

В этом примере будет ваш модульный тест:

var ninja = new Ninja(null);

Выше приведен законный код C # и передается значение null Справочник по модульному тестированию - вполне допустимый способ модульного тестирования областей, которые не нуждаются в зависимости.

3
ответ дан 18 December 2019 в 14:43
поделиться

Я не знаю Ninject, но AFAIK внедрение конструктора обычно используется для обязательных зависимостей, и поэтому null не имеет смысла в этом контексте. Если зависимость не является обязательной, тип должен предоставлять конструктор по умолчанию и использовать инъекцию свойств вместо этого.

Этот пост предоставляет дополнительную информацию.

3
ответ дан 18 December 2019 в 14:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: