Подтвердить что ты не робот

Ninject. Опциональная инъекция

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

Обновление: аргументы конструктора могут быть украшены атрибутом OptionalAttribute. В этом случае нуль вводится, если не найдено соответствующего привязки. Здесь проблема: я не могу проверить, правильно ли построен целевой класс. У меня есть тест для каждой общественной зависимости, которая проверяет, может ли она быть успешно построена. В случае, если значение флага истинно, я не смогу найти ошибку, если зависимость, украшенная атрибутом OptionalAttribute, не может быть построена должным образом. Я хотел бы управлять им только на уровне привязки.

4b9b3361

Ответ 1

Вы можете изменять поведение инъекций путем связывания с помощью метода factory (т.е. ToMethod), и можно разрешить впрыскивание нулей путем настройки контейнера AllowNullInjection.

Другой альтернативой может быть использование метода factory и снабжение легким фиктивным объектом вместо вашего тяжеловесного класса. Если вы используете интерфейсы, это было бы просто, просто реализованы интерфейсы, которые ничего не делают. Вы могли бы даже использовать насмешливую структуру, такую ​​как FakeItEasy, для создания этих манекенов для вас. Преимущество здесь заключается в том, что манекен делает особое поведение прозрачным для клиентов, то есть клиентам не нужно проверять наличие null и т.д.

Пример использования метода factory плюс AllowNullInjection и nulls:

public void Configure()
{
    bool create = true;

    IKernel kernel = new StandardKernel();

    kernel.Settings.AllowNullInjection = true;

    kernel.Bind<IFoo>().ToMethod(ctx => create ? ctx.Kernel.Get<Foo>() : null);

    DependendsOnIFoo depFoo = kernel.Get<DependendsOnIFoo>();
}

private interface IFoo {}

private class Foo : IFoo {}

private class DependendsOnIFoo
{
    public DependendsOnIFoo(IFoo foo) {}
}

И пример замены легкого объекта в зависимости от флага:

public void Configure()
{
    bool heavy = true;

    IKernel kernel = new StandardKernel();

    kernel.Bind<IFoo>()
     .ToMethod(ctx => heavy ? ctx.Kernel.Get<HeavyFoo>() : (IFoo)new DummyFoo());

    DependendsOnIFoo depFoo = kernel.Get<DependendsOnIFoo>();
}

private interface IFoo {}

private class HeavyFoo : IFoo {}

private class DummyFoo : IFoo { }

private class DependendsOnIFoo
{
    public DependendsOnIFoo(IFoo foo) {}
} 

Ответ 2

Инъекция нуля обычно не является разумной идеей. Это будет загрязнять ваш код проверками, если объект имеет значение null или нет, как показано в следующем коде:

public interface IFoo
{
    void Do();
}

public class Foo : IFoo
{
    public void Do()
    {
       DoSomething();
    }
}

public class UglyNullCheckingBar
{
    IFoo foo;
    public Bar(IFoo foo)
    {
        this.foo = foo;
    }

    public void Do()
    {
        if (this.foo != null)
        {
            this.foo.Do();
        }
    }
}

Лучший способ в этом случае - реализовать объект Null, который абсолютно ничего не вводит и вводит вместо него значение null. Это сохраняет ваш код в чистоте.

public class NullFoo : IFoo
{
    public void Do() {}
}

public class Bar
{
    IFoo foo;
    public Bar(IFoo foo)
    {
        this.foo = foo;
    }

    public void Do()
    {
        this.foo.Do();
    }
}