依赖注入 - 参数数量

Dependency Injection - numer of parameters

我有一个 class,它需要很多依赖项 - 在我看来,很多依赖项是 8 个或更多。它在 IDE 中看起来很难看,因为它断行了,在一种情况下我有 3 行构造函数签名:

第一步

public class FooClass
{
    public FooClass(IDependency1 dependency1, IDependency2 dependency2, ..., IDependency8 dependency8, IDependency9 dependency9)
    {
        ...
    }

    ...
}

我决定停止使用这种方法并创建依赖项字典。我取得了什么成就?漂亮的构造函数签名,但可能更容易获得运行时异常。

第二步

public class FooClass2
{
    private IDictionary<Type, object> dependencyDictionary;

    public FooClass2(IDictionary<Type, object> dependencyDictionary)
    {
        this.dependencyDictionary = dependencyDictionary;
        ...
    }

    ...

    public T GetObject<T>()
    {
        return (T)this.dependecyDictionary.FirstOrDefault(t => t.Key == typeof(T));
    }

    // USAGE
    public void FooMethod()
    {
        IDependency1 = this.GetObject<IDependency1>();
        ...
    }
}

但是现在这种类型的注册很难看。作为一个 示例,我使用的是 AutoFac,但任何其他依赖项容器都具有相同的行为。

var builder = new ContainerBuilder();
builder.Register(c => new FooClass2(new Dictionary<Type, object>{
    {typeof(IDependency1), c.Resolve<IDependency1>()},
    {typeof(IDependency2), c.Resolve<IDependency2>()},
    ...
    {typeof(IDependency8), c.Resolve<IDependency8>()},
    {typeof(IDependency9), c.Resolve<IDependency9>()},
})).As<FooClass2>();

当然,为了避免使用第二种方法,我可以创建模型、模板或随意调用它,但它会生成许多额外的 classes,这些仅用于指定依赖项。

第三步

public class FooDependencyDefinition
{

    public FooDependencyDefinition(IDependency1 dependency1, IDependency2 dependency2, ..., IDependency8 dependency8, IDependency9 dependency9)
    {
        this.dependency1 = dependency1;
        ...
    }

    public IDependency1 dependency1;
    public IDependency2 dependency2;

    public IDependency1 dependency1;
    public IDependency2 dependency2;
    ...
    public IDependency8 dependency8;
    public IDependency9 dependency9;
}        

public class FooClass
{
    public FooClass(FooDependencyDefinition dependencyDefinition)
    {
        ...
    }
}

我知道可以通过属性注入,但我想避免它。以上 3 种方法中的哪一种被认为是一种好的做法?您知道将大量依赖项传递给 class 的其他方法吗?

很明显你的Step1不好,因为它有太多的依赖。我们需要一些其他方式。

我强烈反对你的第二步。因为使用依赖注入的想法是让你的依赖对开发者来说是显而易见的。使用您的方法,您很难对 api.

进行推理

第 3 步只是一个 hack。它将负责任地推向其他 class 那里需要丑陋的构造函数。也不推荐它。


当你有太多的依赖时,根据定义,你的 class 做了太多的事情。这也意味着您违反了 Single responsibility principle.

确定 classes 的职责,重构它们以遵循单一职责原则。那么你的 class 将不需要太多的依赖。

Mark Seemann 在这个主题上有一篇很棒的文章 Refactoring to Aggregate Services