依赖注入 - 参数数量
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。
我有一个 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。