将IOC容器用于多种具体类型

时间:2010-11-21 15:59:27

标签: unity-container structuremap ioc-container

我想在我的应用程序中实现IOC,但我很困惑,在我的应用程序中,我有多个实现接口的具体类。请考虑以下情况: -

我有一个Inteface ICommand,并遵循实现此接口的具体类型: -

  • AddAddress
  • AddContact
  • RemoveAddress
  • RemoveContact

用户基本上在UI中执行所有这些操作,然后将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 个答案:

答案 0 :(得分:3)

在这种情况下,您最好将命令转换为值对象,即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 :(得分:1)

如Mark所述,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初始化的实例)是将要返回的实例。

因此,在您的情况下,设置看起来像:

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

Mark会指出这些:

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

希望这有帮助。

答案 2 :(得分:0)

大多数IOC容器允许您注册接口的“命名实例”,允许您注册多个ICommand的实现,每个实现都有自己唯一的名称。在StructureMap中,您可以这样请求它们:

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

查看this question以了解如何在StructureMap中设置容器。