Передача Ninject в значениях конструктора

С Ninject, как вы настраиваете ядро, чтобы я мог определить, какие значения конструктора передаются в экземпляр объекта?

У меня в модуле настроено следующее:

Bind<IService1>()
    .To<Service1Impl>()
    .InSingletonScope()
    .Named("LIVE");
Bind<IService2>()
    .To<Service2Impl>()
    .InSingletonScope()
    .Named("LIVE")
    .WithConstructorArgument(
        "service1", 
        Kernel.Get<IService1>("LIVE"));

Service2Impl принимает параметр конструктора IService1, но я хочу, чтобы это произошло из контейнера. Я также хочу иметь именованные привязки, поскольку мой код будет ориентироваться на разные версии во время выполнения.

Это похоже на работу, но это правильный способ добиться того, что я хочу сделать? Должен ли я достигать без использования названных привязок и подключения различных конфигурационных модулей в ядро?

ИЗМЕНИТЬ

Теперь я использовал метод ToMethod(), чтобы указать делегата для вызова по запросу определенного типа. Это выглядит немного лучше, поскольку я получаю предупреждения о компиляции, если конфигурация конструктора неверна, а не знать имя параметра, который я передаю первым.

Спасибо

Ответы

Ответ 1

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

Например:

.ToMethod(Func<IContext, T> method)

Bind<IWeapon>().ToMethod(context => new Sword());

Ответ 2

Я бы рекомендовал перегрузку WithConstructorParameter, которая принимает лямбда так:

Bind<IService2>()
    .To<Service2Impl>()
    .InSingletonScope()
    .Named("LIVE")
    .WithConstructorArgument(
        "service1", 
        ctx => ctx.Kernel.Get<IService1>("LIVE"));

Это гарантирует, что разрешение IServive1 происходит во время активации Service2Impl, а не при запуске при создании контейнера. Хотя в вашем случае это не имеет особого значения, поскольку Service1Impl является одиночным, могут быть побочные эффекты при выполнении этого в том виде, в котором вы его первоначально написали:

  • Связывание для зависимостей, которое вводится WithConstructorArgument, должно уже существовать. Это означает, что все привязки должны выполняться в определенном порядке. Это создает сложную ситуацию, когда задействовано несколько модулей.

  • Проблемы, связанные с определением области охвата, могут возникать при использовании пользовательской области. Ninject 2.0 представил кеш и собирал управление областью, привязка к константе, скорее всего, приведет к беспорядку.

Ответ 3

Кажется, вы смотрите на это неправильно. Ninject автоматически добавит услугу 1 в службу 2, если она имеет в качестве аргумента конструктора. В этом случае нет необходимости в WithConstructorArgument.

Если есть несколько IService1, вы должны пойти на условия. Например. WhenParentNamed (...)

Ответ 4

Возможно, Поставщики могут вам помочь. Bind IService2 поставщику. и в методе "Создать метод поставщика" используйте Kernel.Get( "LIVE" ) для создания экземпляра Service2Impl.

см. следующую ссылку, чтобы узнать, как использовать провайдер https://github.com/ninject/ninject/wiki/Providers%2C-Factory-Methods-and-the-Activation-Context

Ответ 5

Я думаю, что ToConstant() чище, InSingletonScope неявно:

Bind<IService2>().ToConstant(new Service2Impl(argument)))
                 .Named("LIVE");