使用IOC容器来处理多个具体类型

3
我希望在我的应用程序中实现IOC,但是我很困惑,在我的应用程序中,有多个具体类实现了一个接口。考虑以下情况:
我有一个ICommand接口和以下实现该接口的具体类型:
- AddAddress - AddContact - RemoveAddress - RemoveContact
用户在UI中执行所有这些操作,然后将列表传递到服务层,在那里执行每个命令。
因此,在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
在这种情况下,你最好将你的命令转化为值对象,也就是说,不要由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

正如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");
}

这些将会按照马克的指示被称为:

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

希望这可以帮到你。


0
大多数 IOC 容器都允许您注册接口的“命名实例”,使您可以注册多个 ICommand 实现,每个实现都有自己独特的名称。在 StructureMap 中,您可以这样请求它们:
ObjectFactory.GetNamedInstance<ICommand>("AddAddress");

请查看此问题,了解如何在StructureMap中设置容器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接