Передача 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");