2015-02-19 2 views
2

Большинство моих компонентов зарегистрированы с использованием подхода на основе кода (свободно), но есть один конкретный компонент, который мне нужно решать по-разному во время выполнения. Это интерфейс и несколько конкретных реализации: -Любая альтернатива инъекциям заводов Виндзорской типографии?

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, и пусть что-то где-то выяснит, какую реализацию решить и внедрить - похоже на то, что я делаю сейчас, но раньше в «разрешающем конвейере» Виндзора. Возможно ли подобное?

ответ

2

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

container.Register(Component.For<ICommsService>().UsingFactoryMethod(kernel => kernel.Resolve<ICommsServiceFactory>().Create())); 

Вы можете вводить ICommsService для любого класса в настоящее время. ICommsServiceFactory может быть простым интерфейсом:

interface ICommsServiceFactory 
{ 
    ICommsService Create(); 
} 
+1

Спасибо! Я должен указать, что эта строка должна быть выполнена * по умолчанию * ICommsService, либо путем добавления '.IsDefault()' в конец, либо размещения строки перед моими существующими строками регистрации ICommsService. –

Смежные вопросы