Большинство моих компонентов зарегистрированы с использованием подхода на основе кода (свободно), но есть один конкретный компонент, который мне нужно решать по-разному во время выполнения. Это интерфейс и несколько конкретных реализации: -Любая альтернатива инъекциям заводов Виндзорской типографии?
public interface ICommsService ...
public class SerialCommsService : ICommsService ...
public class TcpCommsService : ICommsService ...
Некоторые из наших пользователей потребуются серийная служба в то время как другие будут нуждаться в службе TCP. Мое текущее решение (которое работает btw) заключается в использовании типизированной фабрики и настраиваемого селектора компонентов - последний считывает параметр app.config, чтобы определить, какая реализация типизированной фабрики будет разрешаться и возвращаться.
Сначала типизированный завод (ничего особенного об этом): -
public interface ICommsServiceFactory
{
ICommsService Create();
void Release(ICommsService component);
}
Далее, селектор пользовательского компонента, который считывает полное имя типа из app.config (например, «MyApp.SomeNamespace.TcpCommsService «): -
public class CommsFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return ConfigurationManager.AppSettings["commsServiceType"];
}
}
Тогда регистрация вещи: -
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>()
.ImplementedBy<CommsFactoryComponentSelector>());
container.Register(Component.For<ICommsFactory>()
.AsFactory(o => o.SelectedWith<CommsFactoryComponentSelector>()));
container.Register(Component.For<ICommsService>()
.ImplementedBy<SerialCommsService>().LifeStyle.Singleton);
container.Register(Component.For<ICommsService>()
.ImplementedBy<TcpCommsService>().LifeStyle.Singleton);
Наконец, пример класса с зависимостью от ICommsService: -
public class Test
{
public Test(ICommsFactory commsFactory)
{
var commsService = commsFactory.Create();
...
}
}
Как уже упоминалось выше, выше решение делает работу, но я не люблю, чтобы впрыснуть завод. Было бы более интуитивно, если бы я мог просто ввести ICommsService
, и пусть что-то где-то выяснит, какую реализацию решить и внедрить - похоже на то, что я делаю сейчас, но раньше в «разрешающем конвейере» Виндзора. Возможно ли подобное?
Спасибо! Я должен указать, что эта строка должна быть выполнена * по умолчанию * ICommsService, либо путем добавления '.IsDefault()' в конец, либо размещения строки перед моими существующими строками регистрации ICommsService. –