Castle Windsor IoC Container Instantiation для нескольких типов бетона

Я новичок в IoC и Castle Windsor.

Вопрос больше связан с IoC, но я просто выбрал Castle в качестве своего любимого оружия.

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

Единственный способ, который кажется мне работающим, - это использовать функцию Builder, которая каждый раз будет строить весь контейнер, а затем позволить мне указать типы, посмотрите на этот пример:

У меня есть мнение:

public interface IView
{
}

Есть две конкретные реализации этого представления:

public class ConcreteViewA : IView
{
}

public class ConcreteViewB : IView
{
}

У меня есть контроллер, который работает с представлением:

public class Controller
{
    public Controller(IView view) { }
    public void Load() { }
}

Я создаю функцию, которая создает мой контейнер IoC и регистрирует общие типы, единственный тип, который я могу зарегистрировать, - это мой контроллер, так как это все, что остается прежним:

WindsorContainer BuildContainer()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<Controller>().ImplementedBy<Controller>());
        return container;
    }

У меня 2 (Root) точки входа:

void RootMethod1()
    {
        var container = BuildContainer();
        container.Register(Component.For<IView>().ImplementedBy<ConcreteViewA>());
        var controller = container.Resolve<Controller>();
        controller.Load();
    }

    void RootMethod2()
    {
        var container = BuildContainer();
        container.Register(Component.For<IView>().ImplementedBy<ConcreteViewB>());
        var controller = container.Resolve<Controller>();
        controller.Load();
    }

Как видите, мне приходится перестраивать контейнер каждый раз, поскольку мне нужно сказать ему, что использовать для IView для каждого контекста, в котором я нахожусь. Что делать, если перестраивать контейнер дорого (много типов и т. Д.), Как я могу дизайн это?


person Andre    schedule 07.10.2011    source источник
comment
Это для приложения MVC? Если да, то что делает экземпляр IView?   -  person Keith Bloom    schedule 10.10.2011
comment
Я спрашиваю, потому что в приложении ASP.Net выбор того, какое представление должно быть возвращено для действия на контроллере, осуществляется фреймворком.   -  person Keith Bloom    schedule 10.10.2011
comment
Нет, это индивидуальная реализация для winforms. Событие загрузки страницы создаст контроллер / презентатор, который принимает представление, которое является текущим экземпляром (поэтому его нельзя создать)   -  person Andre    schedule 11.10.2011
comment
Я не знаю, насколько упрощен этот пример, но обычно контроллер привязан к определенному типу представления. Проблема может быть связана с дизайном, а не с проблемой использования фреймворка.   -  person Krzysztof Kozmic    schedule 12.10.2011
comment
Я согласен с вами, и, как вы можете видеть, мой контроллер зависит от типа IView, но почему мой контроллер должен заботиться о конкретной реализации IView, проблема заключалась в том, чтобы просто сообщать Контейнеру для каждого контекста, что такое конкретное представление. Все остальные типы остаются такими же. Я упростил пример, чтобы получить помощь, но представьте, что контроллеры принимают несколько зависимостей, большинство из которых остаются неизменными и легко обрабатываются ioc, за исключением конкретного представления, которое может меняться.   -  person Andre    schedule 17.10.2011


Ответы (2)


Насколько я понимаю, вам нужны два разных экземпляра класса Controller (каждый из которых построен с различным типом IView). Самый простой способ добиться этого - зарегистрировать два компонента с разными именами и разными зависимостями.

WindsorContainer BuildContainer()
{
    var container = new WindsorContainer();

        container.Register(Component.For<Controller>().Named("ControllerWithViewA")
                                                      .ImplementedBy<Controller>()
                                                      .DependsOn(Property.ForKey(typeof(IView))
                                                      .Is(typeof(ConcreteViewA)));
        container.Register(Component.For<Controller>().Named("ControllerWithViewB")
                                                     .ImplementedBy<Controller>()
                                                     .DependsOn(Property.ForKey(typeof(IView))
                                                     .Is(typeof(ConcreteViewB)));
    return container;
}

Затем вы можете запросить любой контроллер по мере необходимости.

void RootMethod1()
{
    var container = BuildContainer();
    var controller = container.Resolve<Controller>("ControllerWithViewA");
    controller.Load();
}

void RootMethod2()
{
   var controller = container.Resolve<Controller>("ControllerWithViewB");
   controller.Load();
}

Еще несколько вещей, о которых следует помнить при использовании DI

  1. Постройте свой контейнер только один раз (Строить его снова и снова - пустая трата времени и ресурсов).

  2. Будьте очень уверены, какие зависимости внедрять, а какие нет. Чрезмерное использование DI для всего может привести к раздутому контейнеру, что является кошмаром для обслуживания.

  3. Будьте в курсе жизненного цикла ваших компонентов (Singleton, Transient, per thread и т. Д.). Стиль жизни по умолчанию - синглтон, особенно с Castle, что может привести к несогласованному поведению в многопоточном сценарии.

person uttamkini    schedule 11.10.2011

Вы можете посмотреть на использование селектора обработчика. Это позволит вам динамически выбирать, какое представление разрешить, в зависимости от выбранного вами кода. См. здесь.

person Paul Kirby    schedule 07.10.2011