我试图了解什么时候[ImportingConstructor]
比用[import]
. 是个人喜好,还是允许由其他 DI 容器构建类的东西,或者有什么好处[import]
?
我认为,如果您不想公开公共属性,但 MEF 也会解析私有字段,那么再次,好处在哪里?
using 的问题[Import]
在于它将对象的创建分为两个不同且可观察的阶段:创建和初始化。Where[ImportingConstructor]
允许它像其他所有 .Net 对象一样保持为单个阶段。
这种差异可以通过多种方式观察到
[Import]
的会更改类型的逻辑契约。然而,它不会改变公共或使用合同。这意味着即使对象依赖项发生了变化(想想单元测试),之前编译的任何代码都将继续编译。这需要编译时错误并使其成为运行时错误。[Import]
. 合同验证引擎正确识别所有字段都可以作为null
值存在,并且在每次使用字段之前都需要进行检查。 readonly
像使用普通 C# 对象那样表达这一点。与其单纯从 MEF 的角度思考,不如从更广泛的意义上来看待你的课程设计。通常,当您设计一个类时,您有一组关联的属性,这些可能是服务,例如,
public class MyService
{
public ILogger Logger { get; set; }
public void SaySomething()
{
Logger.Log("Something");
}
}
现在,我可以继续创建一个实例:
var service = new MyService();
现在,如果我尝试使用该方法:
service.SaySomething();
如果我不明确知道我还必须初始化我的Logger
属性:
var service = new MyService() { Logger = new ConsoleLogger() };
(或者):
var service = new MyService();
service.Logger = new ConsoleLogger();
然后错误直到运行时才会变得明显。如果我们要重新定义类:
public class MyService
{
private readonly ILogger _logger;
public MyService(ILogger logger)
{
if (logger == null) throw new ArgumentNullException("logger");
_logger = logger;
}
public void SaySomething()
{
_logger.Log("Something");
}
}
现在,如果您尝试创建 的实例MyService
,则必须明确提供此附加服务 ( ILogger
) 才能正确初始化对象。这有助于多种方式:
您可以通过使用代码合同(如@JaredPar 所述)在编译时进行静态检查来进一步改进此设计。
就 MEF 而言,您可以使用 using[Import]
而不是,[ImportingConstructor]
因为当 MEF 不能满足类型的所有导入时,它会抛出异常,并且只会在初始化 ( [ImportingConstructor]
) 和[Import]
s 之后返回类型。
构造函数注入通常是可取的。
通过使用[ImportingConstructor]
,您允许一个用作导出的类来导入其依赖项。这极大地简化了架构,因为您可以将具体对象的依赖关系与其实现分离。
通常,您会使用[ImportingConstructor]
本身标记为[Export]
. 组合类型后,MEF 将提供构造函数参数。
构造函数参数也不支持重组。