DI - 如何"做工作"而不是在构造函数中

时间:2014-09-28 16:09:50

标签: constructor dependency-injection spring.net

理论问题:最佳实践不是在构造函数中做任何工作,不是新事物,除了设置成员之外什么都不做。

在简单示例(依赖注入)中,需要将文件从磁盘加载到成员以使类正常工作,我应该在哪里进行"工作"?在一些初始化函数中,我需要记住调用?

例如:

XDocument.Load(someFilePath) ;

1 个答案:

答案 0 :(得分:2)

最佳做法是不要在注入构造函数中做任何工作,因为Mark Seemann清楚地解释了here。因此,如果您需要从磁盘加载文件,您应该在启动期间(如果可能)执行此操作,或者推迟创建并在构建对象图之后执行此操作。这通常不是一个讨厌的解决方法,而Lazy是推迟创建事物的一个很好的机制。例如:

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>依赖项。例如,假设您有一个ILogger抽象,并且您获得的创建时间非常昂贵。你可能很想开始在所有地方注入Lazy<ILogger>,但是现在你正在泄漏实现细节,因为这个logger创建成本很高的事实是一个实现细节,但是现在{{1}的所有消费者知道这一点,你只需要不小心注入ILogger一次就可以打破这种优化。

因此,创建一个实现ILogger并依赖于ILogger的代理类,并将此代理注入所有使用者。这样所有消费者都可以依赖于Lazy<ILogger>,而无需知道记录器的创建被延迟。