Как сделать правильное контекстное связывание в Ninject? - PullRequest
0 голосов
/ 16 февраля 2019

До сих пор мне удалось легко реализовать контекстную привязку с использованием Unity и Castle Windsor.То есть, учитывая несколько зарегистрированных реализаций интерфейса, я могу зарегистрировать клиентский компонент, который использует их в качестве зависимости для выбора конкретной.Однако в Ninject, похоже, нет такого интерфейса для выполнения этого, и пример, который я нашел на:

https://github.com/ninject/Ninject/wiki/Contextual-Binding#simple-constrained-resolution-named-bindings

Пример Unity:

Данный интерфейс, IFoo и реализации Foo1, Foo2, Foo3.

container.RegisterType<IFoo , Foo1>("Foo1", new TransientLifetimeManager());
container.RegisterType<IFoo , Foo2>("Foo2", new TransientLifetimeManager());
container.RegisterType<IFoo , Foo3>("Foo3", new TransientLifetimeManager());
container.RegisterType<FooClient, FooClient>("FooClient1", new InjectionConstructor(new ResolvedParameter<IFoo>("Foo2")));
var fooClient = container.Resolve<FooClient>("FooClient1");

Пример Castle Windsor:

internal class FooInstaller: IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<IFoo>().Named("Foo1").ImplementedBy<Foo1>().LifeStyle.Transient);
        container.Register(Component.For<IFoo>().Named("Foo2").ImplementedBy<Foo2>().LifeStyle.Transient);
        container.Register(Component.For<IFoo>().Named("Foo3").ImplementedBy<Foo3>().LifeStyle.Transient);
        container.Register(Component.For<FooClient>().LifeStyle.Singleton.DependsOn(ServiceOverride.ForKey<IFoo>().Eq("Foo2")));
    }
}
var fooClient = container.Resolve<FooClient>();

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

class FooClient{
    public FooClient(Named["Foo2"] IFoo fooDependency)
    {
    }
    ....
}

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

Unity & Castle Windsor работал точно так, как ожидалось, fooClient использовал Foo2-реализацию IFoo.Он был автоматически разрешен.

Что касается подхода Ninject, он сработал, но это означает, что он запутан в реализации компонента более высокого уровня, и я нарушил принцип инверсии зависимостей.Хорошая часть подхода Unity / Windsor - корень композиции (настройка IOC) - это точка изоляции.

Есть ли в Ninject API что-то, что я пропустил, что позволило бы мне сохранить DIP?

1 Ответ

0 голосов
/ 03 марта 2019

Условное связывание

Вы можете использовать:

Bind<FooClient>().ToSelf();
Bind<IFoo>().To<Foo2>().WhenInjectedInto<FooClient>();

Параметр связывания

Bind<Foo2>().ToSelf();

Bind<FooClient>().ToSelf()
    .WithConstructorArgument(typeof(IFoo)), ctx => ctx.Kernel.Get<Foo2>());

Примечание: конечно, вы также можете разрешить Kernel.Get<IFoo>("foo2").Примечание. Тип "из памяти" может не компилироваться, поскольку синтаксис может немного отличаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...