【问题标题】:IoC for a list of named objects命名对象列表的 IoC
【发布时间】:2015-08-16 04:58:26
【问题描述】:

我正在寻找有关此问题的建议,以及 service locator 和类命名约定是否是一个好的解决方案(我倾向于避免这些反模式)以及潜在的性能影响。

一个应用程序有一组实现相同接口的对象,按名称区分。例如:

 public interface IDog  {
      void Bark();
 }

 public class Pug: IDog {
      public void Bark() {
         // Pug bark implementation
      }
 }

 public class Beagle: IDog {
      public void Bark() {
         // Beagle bark implementation
      }
 }

在代码中,当您需要 IDog 时,您只知道传递给您的字符串名称,例如“Pug”或“Beagle”。在这种情况下,字符串可能包含特殊字符(例如:<breed:pug />) 已经出现了一些建议的解决方案:

  1. 使用反射,找到所需的实现,其中字符串名称 == 实现名称。
  2. 为每个类添加一个 addribute,使用反射 where string name == attribute property。前 [DogBreed("Pug")]
  3. 向 IDog 界面添加 Breed 属性。将 IList 注入工厂类,并让它检索匹配的狗。前任。

    Private IList _dogs; Public DogFactory(IList<IDog> dogs) { _dogs = dogs; } Public IDog GetDog(string dogBreed) { return _dogs.First(x => x.Breed == dogBreed); }

1 和 2 使用服务定位器。 1 使用隐含的命名约定,只有通过查看反射代码才能知道。 3 问题是所有对象都将构建在内存中,即使您只需要一个实现。

过去我个人倾向于#3。对象创建应该很便宜。但是,这是一个遗留的 Web 应用程序,并且链下的对象可能具有很高的初始化成本。此应用程序使用 Unity for IoC。

【问题讨论】:

    标签: inversion-of-control unity-container factory-pattern


    【解决方案1】:

    选项 1。

    这个选项听起来像Partial Type Name Role Hint 成语。如果你注入候选列表并在这些候选中找到合适的策略,它只是普通的旧构造函数注入,与服务定位器无关(这是一件好事)。

    选项 2。

    这个选项听起来像Metadata Role Hint 成语。同样,如果您通过构造函数注入候选列表,Service Locator 将无处可见。

    选项 3。

    这个选项听起来像是Role Interface Role Hint 成语的变体。仍然支持使用良好的旧构造函数注入。


    就个人而言,我倾向于部分类型名称角色提示,因为这种设计不会影响任何业务逻辑的实现。所有选择逻辑都成为纯粹的基础架构问题,并且可以独立定义为实现和客户端。

    说到组成相关对象图的成本,有办法address any issues in clean ways

    【讨论】:

    • 谢谢马克!在示例中,您是说通过构造函数注入通过集合注入所有候选对象(以避免服务定位器)?唯一的区别是我们如何获得正确的实现?问题是对象会在需要之前被实例化(而大多数对象都不需要)。
    • @RyanLangton 在大多数情况下,如果您真的测量,那么实例化的成本可以忽略不计。在成本不可可以忽略不计的少数情况下,您可以通过各种方式解决问题,包括单例或池化生命周期以及虚拟代理,如此处所述blog.ploeh.dk/2011/03/04/Composeobjectgraphswithconfidence
    猜你喜欢
    • 2019-12-17
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 2012-11-06
    • 1970-01-01
    相关资源
    最近更新 更多