Использование контейнера IOC для нескольких конкретных типов - PullRequest
3 голосов
/ 21 ноября 2010

Я хочу реализовать IOC в своем приложении, но я в замешательстве, в моем приложении у меня есть несколько конкретных классов, которые реализуют интерфейс. Рассмотрим этот сценарий: -

У меня есть Inteface ICommand и следующие конкретные типы, которые реализуют этот интерфейс: -

  • AddAddress
  • AddContact
  • RemoveAddress
  • RemoveContact

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

Так что в слое GUI я напишу

ICommand command1 = new AddAddress();
ICommand command2 = new RemoveContact();

В диспетчере команд

List<ICommand> listOfCommands = List<ICommand>();
listOfCommands.Add(command1);
listOfCommands.Add(command2);

Затем, наконец, передаст listOfCommands слою сервиса.

Теперь, согласно моему пониманию IOC, только один конкретный класс сопоставлен с интерфейсом. И мы используем этот синтаксис для получения нашего конкретного типа из контейнера StructureMap.

ICommand command = ObjectFactory.GetInstance<ICommand>();

Как мне реализовать IOC в этом сценарии?

Ответы [ 3 ]

3 голосов
/ 21 ноября 2010

В этом сценарии вам лучше превратить ваши команды в объекты-значения, то есть , а не , созданные контейнером IoC:

class AddAddressCommand {
    public AddAddressCommand(string address) {
        Address = address;
    }
    public string Address { get; private set; }
}

Когда вы создаете команду, вы действительно делаетевам нужна конкретная реализация, и вы хотите точно ее параметризировать, обе эти проблемы будут работать против служб контейнера IoC.Это станет еще более актуальным, если в какой-то момент вы решите сериализовать объекты команд.

Вместо этого сделайте компоненты уровня обслуживания, которые выполняют команды, в компоненты, предоставляемые IoC:

class AddAddressHandler : IHandler<AddAddressCommand> {
    public AddAddressHandler(ISomeDependency someDependency) { ... }
    public void Handle(AddAddressCommand command) {
        // Execution logic using dependencies goes here
    }
}

В вашем случае компоненту, который принимает список команд для выполнения, потребуется разрешить соответствующий обработчик для каждой команды и передать ей объект команды.

Существует некоторое обсуждение того, каксделать это с Windsor можно здесь: http://devlicious.com/blogs/krzysztof_kozmic/archive/2010/03/11/advanced-castle-windsor-generic-typed-factories-auto-release-and-more.aspx - сообщество, поддерживающее выбранный вами контейнер IoC, сможет помочь вам с его настройкой.

1 голос
/ 24 ноября 2010

Как уже упоминал Марк, StructureMap позволит вам настроить и вызвать именованные экземпляры интерфейса:

ObjectFactory.Initialize(x =>
{
   x.For<ISomeInterface>().Add<SomeImplementation>().Named("SomeName");
}

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

ObjectFactory.Initialize(x =>
{
  x.For<ISomeInterface>().Add<DefaultImplementation>();       
  x.For<ISomeInterface>().Add<SomeImplementation>().Named("SomeName");
}

Когда вы вызываете ObjectFactory.GetInstance<ISomeInterface>();, экземпляр по умолчанию (инициализированный Use вместо Add) является тем, который будет возвращен.

Итак, в вашем случае наборup будет выглядеть примерно так:

ObjectFactory.Initialize(x =>
{
   // names are arbitrary
   x.For<ICommand>().Add<AddAddress>().Named("AddAddress");
   x.For<ICommand>().Add<RemoveContact>().Named("RemoveContact");
}

Они будут вызваны, как указано Марком:

ObjectFactory.GetNamedInstance<ICommand>("AddAddress");
ObjectFactory.GetNamedInstance<ICommand>("RemoveContact");

Надеюсь, это поможет.

0 голосов
/ 21 ноября 2010

Большинство контейнеров IOC позволяют регистрировать «именованные экземпляры» интерфейсов, что позволяет зарегистрировать несколько реализаций ICommand, каждая из которых имеет свое уникальное имя. В StructureMap вы запрашиваете их следующим образом:

ObjectFactory.GetNamedInstance<ICommand>("AddAddress");

Посмотрите на этот вопрос , чтобы увидеть, как вы настраиваете контейнер в StructureMap.

...