Для конкретного контроллера заставьте Виндзор создавать экземпляры разных классов - PullRequest
3 голосов
/ 15 марта 2011

Я использую S # arp Architecture, которая использует Виндзорский замок для IoC.Теперь у меня есть новый контроллер, который, в отличие от всех других контроллеров в проекте, требует другой реализации тех же интерфейсов.Т.е. все контроллеры используют ProductsRepository: IProductsRepository в качестве реализации, но новый должен использовать SpecificProductsRepository.

Как настроить его для автоматического распознавания и управления этим?Либо чисто виндзорским способом, либо с помощью ASP.NET MVC (например, на моей фабрике пользовательских контроллеров).

ОК, похоже, мне нужны субконтейнеры.Все еще в поисках.

Ответы [ 2 ]

6 голосов
/ 15 марта 2011

Более простым и намного более простым способом было бы использовать переопределения службы Windsor.

Например, зарегистрируйте свои репозитории следующим образом:

container.Register(Component.For<IProductsRepository>
                     .ImplementedBy<ProductsRepository>()
                     .Named("defaultProductsRepository"),
                   Component.For<IProductsRepository>
                     .ImplementedBy<SpecificProductsRepository>()
                     .Named("specificProductsRepository"));

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

container.Register(Component.For<NewController>()
     .ServiceOverrides(ServiceOverride
          .ForKey("productsRepository")
          .Eq("specificProductsRepository"));

Вы можете прочитать документы здесь .

Редактировать: если вы хотите зарегистрировать свойВ репозиториях с помощью AllTypes вы можете настроить регистрационный ключ, например, так:

container.Register(AllTypes.[how you used to].Configure(c => c.Named(GetKey(c)));

, где GetKey например, может быть что-то вроде:

public string GetKey(ComponentRegistration registration)
{
    return registration.Implementation.Name;
}
0 голосов
/ 15 марта 2011

Хорошо, в наши дни я склонен отвечать на свои вопросы ... так что это для тех, кому это нужно.

     // create subcontainer with specific implementation
     var mycontainer = new WindsorContainer();
     mycontainer.Register(AllTypes.Pick()
        .FromAssemblyNamed("My.Data")
        .WithService.FirstInterface()
        .Where(x => x.Namespace == "My.Data.Custom")
        .Configure(x => x.LifeStyle.Is(LifestyleType.PerWebRequest)));
     container.AddChildContainer(mycontainer);

     ControllerBuilder.Current.SetControllerFactory(new ExtendedControllerFactory(
        new Dictionary<string, IWindsorContainer> { {"", container}, {"Lm", mycontainer} }));

Фабрика контроллеров выбирает подходящий контейнер на основе имени.Самой большой проблемой является вызов соответствующего контейнера Release (контроллера) в конце запроса, т. Е. Запоминание того, какой контейнер использовался для создания экземпляра контроллера.Но это может быть решено несколькими способами, я полагаю - запомните в специфичном для потока (в HttpContext), запомните в свойстве BaseController, запомните во внутреннем словаре и т. Д.

...