Создание использования экземпляра Ninject с дополнительными параметрами в конструкторе

Я решил начать использовать Ninject и сталкиваться с проблемой. Скажите, что у меня есть следующий сценарий. Я имею IService взаимодействуйте через интерфейс и 2 класса, реализовывая этот интерфейс. И также у меня есть класс, который имеет конструктора, получающего IService и интервал. Как я могу создать экземпляр этого класса с Ninject (я не хочу соединять этот интервал проводами, я хочу передать его каждый раз, когда я получаю экземпляр)?

Вот некоторый код, иллюстрирующий ситуацию:

interface IService
{
    void Func();
}

class StandardService : IService
{
    public void Func()
    {
        Console.WriteLine("Standard");
    }
}

class AlternativeService : IService
{
    public void Func()
    {
        Console.WriteLine("Alternative");
    }
}


class MyClass
{
    public MyClass(IService service, int i)
    {
        this.service = service;
    }

    public void Func()
    {
        service.Func();
    }

    IService service = null;
}
class Program
{
    static void Main(string[] args)
    {
        IKernel kernel = new StandardKernel(new InlineModule(
            x => x.Bind<IService>().To<AlternativeService>(),
            x => x.Bind<MyClass>().ToSelf()));

        IService service = kernel.Get<IService>();

        MyClass m = kernel.Get<MyClass>();
        m.Func();
    }
}
63
задан Ruben Bartelink 10 July 2012 в 08:12
поделиться

1 ответ

Для этой цели в 1.0 существовал аргумент With.ConstructorArgument . В версии 2.0 синтаксис немного изменился: - With.Parameters.ConstructorArgument с ninject 2.0

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

РЕДАКТИРОВАТЬ: Поскольку Стивен решил притвориться, что мой комментарий не имеет отношения к делу, я лучше проясню то, что я говорю, с помощью нескольких примеров (для 2.0):

MyClass m = kernel.Get<MyClass>( new ConstructorArgument( "i", 2) );

который, на мой взгляд, очень ясен и точно описывает, что происходит.

Если вы находитесь в положении, когда вы можете определить параметр более глобальным способом, вы можете зарегистрировать поставщика и сделать это следующим образом:

class MyClassProvider : SimpleProvider<MyClass>
{
    protected override MyClass CreateInstance( IContext context )
    {
        return new MyClass( context.Kernel.Get<IService>(), CalculateINow() );
    }
}

И зарегистрировать его так:

x => x.Bind<MyClass>().ToProvider( new MyClassProvider() )

NB CalculateINow () бит - это то место, где вы должны вставить свою логику, как в первом ответе.

Или сделайте его более сложным, например:

class MyClassProviderCustom : SimpleProvider<MyClass>
{
    readonly Func<int> _calculateINow;
    public MyClassProviderCustom( Func<int> calculateINow )
    {
        _calculateINow = calculateINow;
    }

    protected override MyClass CreateInstance( IContext context )
    {
        return new MyClass( context.Kernel.Get<IService>(), _calculateINow() );
    }
}

Что вы должны зарегистрировать так:

x => x.Bind<MyClass>().ToProvider( new MyClassProviderCustom( (  ) => new Random( ).Next( 9 ) ) )

ОБНОВЛЕНИЕ: Новые механизмы, которые демонстрируют значительно улучшенные шаблоны с меньшим количеством шаблонов, чем приведенные выше, воплощены в Ninject.Extensions .Factory , см .: https://github.com/ninject/ninject.extensions.factory/wiki

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

Последнее соображение заключается в том, что, поскольку вы не указали с помощью , по умолчанию будет использоваться значение по умолчанию, как указано / по умолчанию в параметрах ядра ( TransientBehavior в примере), который может отображать тот факт, что фабрика вычисляет i на ходу [например, если объект был кэширован]

Теперь, чтобы прояснить некоторые другие моменты в комментариях, которые быть FUDed и замалчивается. Некоторые важные моменты, которые следует учитывать при использовании DI, будь то Ninject или что-то еще:

  1. Сделайте как можно больше с помощью внедрения конструктора, чтобы вам не нужно было использовать специфические для контейнера атрибуты и уловки.В блоге есть хорошая запись под названием Ваш контейнер IoC показывает .

  2. Сведите к минимуму код, идущий к контейнеру и запрашивающий материалы - в противном случае ваш код будет связан с а) конкретным контейнером (который CSL может минимизировать) б) способом, которым построен весь ваш проект. Об этом есть хорошие сообщения в блогах, показывающие, что CSL не делает то, что вы думаете. Эта общая тема называется Размещение службы и внедрение зависимостей . ОБНОВЛЕНИЕ: см. http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx для подробного и полного обоснования.

  3. Минимизируйте использование статики и синглтонов

  4. Не предполагайте, что существует только один [глобальный] контейнер, и что это нормально - просто запрашивать его всякий раз, когда он вам нужен, как хорошая глобальная переменная. Правильное использование нескольких модулей и Bind.ToProvider () дает вам структуру для управления этим. Таким образом, каждая отдельная подсистема может работать сама по себе, и у вас не будет компонентов нижнего уровня, привязанных к компонентам верхнего уровня и т. Д.

Если кто-то хочет заполнить ссылки на блоги, о которых я говорю, я ' Я ценю это (все они уже связаны из других сообщений на SO, так что все это просто дублирование, введенное пользовательским интерфейсом с целью избежать путаницы с вводящим в заблуждение ответом.)

Итак, если бы только Джоэл мог войти и действительно объяснить мне, какой хороший синтаксис и / или правильный способ сделать это!

ОБНОВЛЕНИЕ: хотя этот ответ явно полезен по количеству набранных голосов, я хотел бы сделать следующие рекомендации:

  • Вышеупомянутое кажется немного устаревшим и, честно говоря, отражает множество неполных размышлений. что почти неловко с тех пор, как я прочитал Внедрение зависимостей в .net - Запустите и купите сейчас - это не только о DI,первая половина - это полное рассмотрение всех связанных с архитектурой проблем, связанных с ней, от человека, который провел здесь слишком много времени, слоняясь по тегу внедрения зависимостей.
  • Прочтите сообщения Марка Seemann с самым высоким рейтингом здесь, на SO прямо сейчас - вы узнаете ценные техники от каждого
93
ответ дан 24 November 2019 в 16:25
поделиться
Другие вопросы по тегам:

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