2016-07-14 4 views
1

У меня есть компонент с несколькими зависимостями:Могу ли я использовать дочерний контейнер в качестве фабрики для компонента со сложными зависимостями?

class Service 
{ 
    public Service(IDependencyA a, IDependencyB b, ...) { ... } 
} 

где некоторые зависимости имеют единственную реализацию:

class CommonDependencyA : IDependencyA 
{ 
    ... 
} 

и некоторые имеют несколько реализаций:

class FooDependencyB : IDependencyB 
{ 
    public FooDependencyB(IDependencyC c, ...) { ... } 
} 

class BarDependencyB : IDependencyB 
{ 
    public BarDependencyB(IDependencyC c, ...) { ... } 
} 

class FooDependencyC : IDependencyC 
{ 
    ... 
} 

class BarDependencyC : IDependencyC 
{ 
    ... 
} 

Иногда я хочу, чтобы разрешить Service класса с использованием реализаций «Bar», в то время как в других случаях мне нужны реализации «Foo».

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

public Service CreateService(IWindsorContainer parent, FooBarType type) 
{ 
    using(IWindsorContainer child = SetupChildContainer(parent)) 
    { 
     if (type == FooBarType.Foo) 
     { 
      child.Register(Component.For<IDependencyC>.ImplementedBy<FooDependencyC>().LifeStyle.Transient); 
      child.Register(Component.For<IDependencyB>.ImplementedBy<FooDependencyB>().LifeStyle.Transient); 
      ... 
     } 
     else 
     { 
      //register "Bar" implementations 
     } 
     child.Register(Component.For<Service>.LifeStyle.Transient); 
     return child.Resolve<Service>(); 
    } 
} 

Я тогда реорганизовать этот метод в фабрику, и зарегистрировать этот завод внутри родительского контейнера.

Что мне не нравится в этом подходе, так это то, что каждый раз, когда мне нужно разрешать обслуживание, я должен сделать регистрацию. Я также прочитал утверждение, что использование дочернего контейнера почти всегда является неправильным решением. Итак, я делаю это неправильно? Есть ли лучший подход? Я предпочел бы просто зарегистрировать все компоненты сразу, а затем вызвать что-то вроде:

var fooService = container.Resolve<Service>(new []{FooBarType.Foo}); 

и сделать Widsor выяснить правильную зависимость. Но я не знаю, как сделать регистрацию, чтобы это работало.

+0

Я думаю, что тот факт, что вам не нравится ваш подход, предполагает, что использование детского контейнера является излишним. Вы можете попробовать использовать типизированную фабрику: http://stackoverflow.com/questions/14318582/windsor-resolve-dependencies-using-a-key или разрешить с параметрами: http://stackoverflow.com/questions/18048229/замок-Виндзорский-решимость-метод-почему пасс аргументы-что-это-они-для – Thuan

ответ

0

Я закончил с использованием названных зависимостей:

container.Register(Component.For<IDependencyA>().ImplementedBy<CommonDependencyA>()); 
container.Register(Component.For<IDependencyC>().ImplementedBy<FooDependencyC>() 
          .Named("FooDependencyC")); 
container.Register(Component.For<IDependencyB>().ImplementedBy<FooDependencyB>() 
          .Named("FooDependencyB") 
          .DependsOn(Dependency.OnComponent(typeof(IDependencyC), "FooDependencyC")); 
container.Register(Component.For<Service>(). 
          .Named("FooService") 
          .DependsOn(Dependency.OnComponent(typeof(IDependencyB), "FooDependencyB")); 

Не то, что я надеялся (я ненавижу использование имен), но достаточно хорошо в моем случае.

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

  • Нет связанных вопросов^_^