理论问题:最佳实践不是在构造函数中做任何工作,不是新建,除设置成员外没有任何工作。DI - 如何做“工作”,而不是在构造函数中
在简单的例子(依赖注入),需要从磁盘加载文件到成员为了类正常工作,我应该在哪里做“工作”?在一些初始化函数中,我需要记住调用?
例如:
XDocument.Load(someFilePath) ;
理论问题:最佳实践不是在构造函数中做任何工作,不是新建,除设置成员外没有任何工作。DI - 如何做“工作”,而不是在构造函数中
在简单的例子(依赖注入),需要从磁盘加载文件到成员为了类正常工作,我应该在哪里做“工作”?在一些初始化函数中,我需要记住调用?
例如:
XDocument.Load(someFilePath) ;
最好的做法是不要做任何工作注射构造马克塞曼清楚地解释here。因此,如果您需要从磁盘加载文件,则应该在启动过程中(如果可能)执行该操作,或者在创建对象图之后延迟创建并执行该操作。这通常不是一个讨厌的解决方法,懒惰是推迟创建事物的一个很好的机制。例如:
class ApplicationConfiguration
{
private readonly Lazy<XDocument> configFile;
public ApplicationConfiguration(Lazy<XDocument> configFile) {
this.configFile = configFile;
}
public T GetValue<T>(string key) {
return (T)this.configFile.Value.Root.Find(key).Value;
}
}
但是关于Lazy<T>
的一个警告。虽然它可以(也应该)被用来推迟创建事物,但确保你不会将它当作漏洞抽象。例如,不要在许多类中注入相同的Lazy<T>
依赖项。例如,假设你有一个抽象,并且你得到了一个创建时间很昂贵的实现。你可能会开始在各处注入Lazy<ILogger>
,但现在你泄漏了实现细节,因为这个记录器创建起来很昂贵的事实是一个实现细节,但现在所有的消费者都知道这个,而你只是必须直接意外地注入一次以打破此优化。
相反,创建代理类实现并取决于Lazy<ILogger>
并将此代理注入所有使用者。通过这种方式,所有消费者都可以依靠,而不需要知道记录器的创建是否延迟。