是否有混合注射的替代方案?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (18)

public class ThingMaker {
    ...
    public ThingMaker(IThingSource source){
        _source = source;
    }

但是,对于我打算作为公共API(其他开发团队将使用的类)的类,我永远找不到比编写具有最可能需要的依赖性的默认“混蛋”构造函数更好的选项:

    public ThingMaker() : this(new DefaultThingSource()) {} 
    ...
}

这里明显的缺点是这会在DefaultThingSource上创建静态依赖关系; 理想情况下,不存在这样的依赖关系,并且消费者总是会注入他们想要的任何IThingSource。但是,这太难使用了; 消费者希望创造一个ThingMaker并开始制作东西,然后在需要时再注入其他东西。在我看来,这只剩下几个选项:

  1. 省略混蛋构造函数; 迫使ThingMaker的用户了解IThingSource,了解ThingMaker如何与IThingSource交互,查找或编写具体类,然后在其构造函数调用中注入实例。
  2. 省略混蛋构造函数并提供单独的工厂,容器或其他引导类/方法; 以某种方式让消费者明白他们不需要编写自己的IThingSource; 迫使ThingMaker的消费者找到并理解工厂或引导程序并使用它。
  3. 保持混蛋的构造函数,使消费者“新建”一个对象并运行它,并应对DefaultThingSource上的可选静态依赖。

#3肯定看起来很有吸引力。还有其他更好的选择吗?#1或#2似乎不值得。

提问于
用户回答回答于

据我所知,这个问题涉及如何使用一些适当的默认值公开一个松散耦合的API。在这种情况下,你可能拥有一个良好的本地默认值,在这种情况下,可以将依赖关系视为可选项。处理可选依赖关系的一种方法是使用属性注入而不是构造器注入 - 事实上,这是属性注入的一种海报方案。

但是,Bastard Injection的真正危险在于默认值为Foreign Default时,因为这意味着默认构造函数会拖拽到实现默认值的程序集的不希望的耦合。然而,据我了解这个问题,预期的违约将源于同一个集会,在这种情况下,我没有看到任何特别的危险。

用户回答回答于

1)唯一构造函数是参数化的构造函数

2)使用工厂方法创建ThingMaker并传入该默认源。

public class ThingMaker {
  public ThingMaker(IThingSource source){
    _source = source;
  }

  public static ThingMaker CreateDefault() {
    return new ThingMaker(new DefaultThingSource());
  }
}

显然这并不能消除你的依赖关系,但它确实使我更清楚的知道,这个对象具有依赖关系,如果调用者关心,它可以深入其中。如果你喜欢(CreateThingMakerWithDefaultThingSource),那么你可以使该工厂方法更加明确,如果这有助于理解。我更喜欢重写IThingSource工厂方法,因为它继续支持组合。当DefaultThingSource已过时时,您也可以添加一个新的工厂方法,并且有一个明确的方法可以使用DefaultThingSource查找所有代码并将其标记为要升级。

扫码关注云+社区