【问题标题】:Using IOC Container for multiple concrete types将 IOC Container 用于多种具体类型
【发布时间】:2010-11-21 15:59:27
【问题描述】:

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

我有一个接口 ICommand 和以下实现此接口的具体类型:-

  • 地址
  • 添加联系人
  • 删除地址
  • 删除联系人

基本上用户在 UI 中执行所有这些操作,然后将 List 传递到执行每个命令的服务层。

所以在GUI层我会写

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

在命令管理器中

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

然后 finally 将 listOfCommands 传递给服务层。

现在根据我对 IOC 的理解,只有一个具体的类映射到接口。我们使用这种语法从 StructureMap 容器中获取我们的具体类型。

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

在这种情况下我应该如何实现 IOC?

【问题讨论】:

    标签: unity-container structuremap ioc-container


    【解决方案1】:

    在这种情况下,你最好将你的命令变成值对象,即 不是由 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 容器的社区将能够帮助您进行配置。

    【讨论】:

      【解决方案2】:

      正如 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&lt;ISomeInterface&gt;(); 时,默认实例(使用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");
      

      希望这会有所帮助。

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-23
          相关资源
          最近更新 更多