在少数情况下,我最常被诱惑使用"私生子注射".当我拥有一个"适当的"依赖项注入构造函数时:

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

但是,对于我预期的public APIs个类(其他开发团队将使用的类),我再也找不到比编写一个具有最可能需要的依赖关系的默认"混蛋"构造函数更好的 Select 了:

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

这里明显的缺点是,这会创建对DefaultThingSource的静态依赖;理想情况下,不会有这种依赖性,消费者总是会注入他们想要的任何信息源.然而,这太难使用了;消费者希望新成立一家产品制造商,开始生产产品,然后在几个月后需要时注入其他产品.在我看来,这只剩下几个选项:

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

天哪,3号看起来确实很吸引人.还有其他更好的 Select 吗?#1或#2似乎不值得.

推荐答案

据我所知,这个问题涉及如何用一些适当的默认值公开松散耦合的API.在这种情况下,您可能有一个良好的Local Default,在这种情况下,可以将依赖项视为可选.处理optional dependencies的一种方法是使用Property Injection而不是Constructor Injection-事实上,这是属性注入的典型场景.

然而,Bastard注入的真正危险是当默认值为Foreign Default时,因为这将意味着默认构造函数拖着不需要的耦合到实现默认的程序集.然而,根据我对这个问题的理解,预期的违约将源于同一程序集,在这种情况下,我看不到任何特别的危险.

在任何情况下,你也可以考虑我前面一个答案中所描述的外观:Dependency Inject (DI) "friendly" library.

顺便说一句,这里使用的术语是基于my book的模式语言.

.net相关问答推荐

EF核心类似功能T-SQL UPDATE FROM

从没有流的EventStore中读取流不存在异常

PowerShell中窗体定时器和系统定时器的统一处理

如何将 signalR 添加到不同项目中的后台服务?

正则表达式匹配 URL 中的多个子目录

.NET 中两个子字符串之间的非贪婪正则表达式匹配

为什么 StyleCop 建议在方法或属性调用前加上this?

.NET 的 Visual Studio 调试器提示和技巧

发布版本中的 Debug.WriteLine

在 WinForms 应用程序中查找焦点控件的首选方法是什么?

.NET 的 `Array.Sort()` 方法使用的排序算法是稳定的算法吗?

IIS Express - 500.19 无法读取配置文件 - 因为它正在查看错误的路径

String.Split 仅在 C# 中的第一个分隔符上?

X509Certificate 构造函数异常

文件按文件名模式存在

清除文件内容

如何使用通用扩展方法中的字符串列名在 IQueryable 上应用 OrderBy?

对构造函数进行单元测试重要吗?

如何在不使用 3rd 方库的情况下登录 C#?

Windows 服务在哪个目录中运行?