Передача Ninject значений конструктора - PullRequest
13 голосов
/ 20 мая 2011

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

В модуле настроено следующее:

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

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

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

EDIT

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

Спасибо

Ответы [ 5 ]

17 голосов
/ 20 мая 2011

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

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

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

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

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

14 голосов
/ 01 июня 2011

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

Например:

.ToMethod(Func<IContext, T> method)

Bind<IWeapon>().ToMethod(context => new Sword());
6 голосов
/ 23 мая 2011

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

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

0 голосов
/ 21 февраля 2014

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

Bind<IService2>().ToConstant(new Service2Impl(argument)))
                 .Named("LIVE");
0 голосов
/ 20 мая 2011

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

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

...