注入什么类型的依赖?

时间:2010-11-04 14:40:53

标签: dependency-injection

我有一个验证代码的规范。它看起来如下:

public ClassificationSpecification : ISpecification<Classification> {
    HashSet<string> codes;

    // constructor elided

    public IsSatisfiedBy(Classification classification) {
        return codes.Contains(classification.Code);
    }
}

有效代码来自数据库中的Classification表。我的问题是,哪个是更好的依赖注入构造函数?

public CodeSpecification(IEnumerable<string> codes) {
    this.codes = new HashSet<string>(codes);
}

public CodeSpecification(IRepository<Classification> repository) {
    this.codes = new HashSet<string>(repository.Select(x => x.Code));
}

所有重要的问题:为什么?

2 个答案:

答案 0 :(得分:1)

我会使用这个构造函数:

private readonly IRepository<Classification> _repository;

public CodeSpecification(IRepository<Classification> repository)
{
    _repository = repository;
}

然后,在实际调用您的类时找到有效代码:

public bool IsSatisfiedBy(Classification classification)
{
    var _repository.Any(x => x.Code == classification.Code);
}

这确保在需要之前不会完成任何实际工作,将应用程序的初始化与运行时分开。它还确保您始终使用IsSatisfiedBy中的新数据;缓存构造函数中的值会引入一段时间,存储库中的代码可能会发生变化。

如果代码数量很大,并且存储库不能有效地执行Any,您可能仍希望实现缓存。在第一次调用IsSatisfiedBy

之前,最好遵循相同的建议而不是缓存
private readonly HashSet<string> _codes;
private readonly object _codesSync = new object();

public bool IsSatisfiedBy(Classification classification)
{
    if(_codes == null)
    {
        lock(_codesSync)
        {
            if(_codes == null)
            {
                _codes = new HashSet<string>(_repository.Select(x => x.Code));
            }
        }
    }

    return _codes.Contains(classification.Code);
}

依赖注入对象中的构造函数是基础结构元素;通常应推迟任何类型的域逻辑,直到另一个域调用该对象。

答案 1 :(得分:1)

你的第二个构造函数是真正的工作(通过存储库),这是一个坏主意。见http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/

您需要确定加载所有值(传递构造函数所需的值)是否有效,或者您希望在每次调用时查找它们(在构造函数中传入存储库并存储它)。