Как решаются случаи, когда используются дочерние контейнеры? - PullRequest
4 голосов
/ 23 ноября 2010

во фрагменте кода ниже у нас есть корневой контейнер и один дочерний контейнер.Дочерний контейнер содержит регистрацию для Person, которая зависит от INameProvider, определенного в корневом контейнере.INameProvider в свою очередь зависит от IInfoProvider, который имеет регистрацию в обоих контейнерах.

Когда дочернему контейнеру предлагается разрешить экземпляр Person, механизм использует корневой контейнер для разрешения экземпляра INameProvider (как и ожидалось), но также для разрешения экземпляра IInfoProvider,Я ожидаю, что регистрация для IInfoProvider в дочернем контейнере переопределит регистрацию в корневом контейнере.

WindsorContainer rootContainer = new WindsorContainer();

// register components for root container
rootContainer.Register(
   Castle.MicroKernel.Registration.Component.For<IInfoProvider>().
      ImplementedBy<InfoProvider>().
      LifeStyle.Transient);
rootContainer.Register(
   Castle.MicroKernel.Registration.Component.For<INameProvider>().
      ImplementedBy<BobNameProvider>().
      LifeStyle.Transient);

// create child container
WindsorContainer childContainer = new WindsorContainer();
rootContainer.AddChildContainer(childContainer);

// register components for child container
childContainer.Register(
   Castle.MicroKernel.Registration.Component.For<Person>().
      LifeStyle.Transient);
childContainer.Register(
   Castle.MicroKernel.Registration.Component.For<INameProvider>().
      ImplementedBy<JimNameProvider>().
      LifeStyle.Transient);

var person = childContainer.Resolve<Person>();

Debug.Assert(person.ToString() == "Jim"); // <- fails, because person.ToString is "Bob"

Более того, если мы используем дочерний контейнер для разрешения экземпляра INameProvider (как в фрагменте ниже), дочерний контейнер будет , используемый для получения экземпляра IInfoProvider.Это то, чего я ожидаю.

var np = childContainer.Resolve<INameProvider>();
np.ToString() // <-- equals "Jim"

Кто-нибудь может объяснить, почему в первом примере используется корневой контейнер для разрешения IInfoProvider вместо дочернего контейнера?

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

Обновление # 1 Реальная ситуация, с которой мы имеем дело, заключается в следующем.Мы разрабатываем мультитенантное веб-приложение MVC, в котором общие функциональные возможности приложения хранятся в корневом контейнере, и у каждого арендатора есть собственный дочерний контейнер, в котором определенные вещи переопределяются.Например, конфигурация хранилища данных хранится в каждом дочернем контейнере (у каждого арендатора есть своя собственная база данных), а некоторые контроллеры MVC отличаются.Когда контроллер создан, мы ищем дочерний контейнер с помощью Container.GetChildContainer и пытаемся разрешить нужные нам объекты.Наш контроллер имеет косвенную зависимость от конфигурации хранилища данных, но тот, который определен в дочернем контейнере, никогда не используется.

...