C# 注入作为依赖项树的依赖项
注入依赖项是依赖项树,这是一种模式还是反模式 例如:C# 注入作为依赖项树的依赖项,c#,design-patterns,dependency-injection,anti-patterns,C#,Design Patterns,Dependency Injection,Anti Patterns,注入依赖项是依赖项树,这是一种模式还是反模式 例如: public class ClassExample { private IContainer _container; public ClassExample(IContainer container) { _container = container; } } public interface IContainer { IDependencyA DependencyA { get;
public class ClassExample
{
private IContainer _container;
public ClassExample(IContainer container)
{
_container = container;
}
}
public interface IContainer
{
IDependencyA DependencyA { get; set; }
IDependencyB DependencyB { get; set; }
IDependencyC DependencyC { get; set; }
}
public interface IDependencyA
{
}
public interface IDependencyB
{
}
public interface IDependencyC
{
}
上面的例子可以做得更深入(一棵树)——例如IDependencyA可以包含更多的依赖项IDependencyAA、IDependencyAB等等
当需要注入同一组服务的多个位置时,有人可能会使用上述方法来最小化代码重复。在许多情况下,代码最终会看起来像:container.DependencyA.DependencyAA.Method(…)
,这会使它更冗长、更枯燥
使用上述方法是好主意还是坏主意(模式/反模式)?或者什么时候这是个好主意,什么时候是个坏主意?我认为这不是一个特别好的模式*,但同样的道理,这不会产生很大的影响 如果使用您的示例,
ClassExample
依赖于IDependencyA
,IDependencyB
&IDependencyC
,那么它们都应该作为依赖项注入
更常见的是,IDependencyXX
类的具体实现本身具有依赖性,但不会像您描述的那样将它们公开给ClassExample
*这是一个错误的决定,主要是因为人们迟早会在只需要
IDependencyA
和IDependencyB
(而不是IDependencyC
)的时候开始注射IContainer
。这是多余的。注入的全部要点是注入您需要的依赖项,而不是来自系统的所有可能的依赖项“以防万一”我不认为这是一种特别好的模式*,但同样地,它不会产生巨大的差异
如果使用您的示例,ClassExample
依赖于IDependencyA
,IDependencyB
&IDependencyC
,那么它们都应该作为依赖项注入
更常见的是,IDependencyXX
类的具体实现本身具有依赖性,但不会像您描述的那样将它们公开给ClassExample
*这是一个错误的决定,主要是因为人们迟早会在只需要
IDependencyA
和IDependencyB
(而不是IDependencyC
)的时候开始注射IContainer
。这是多余的。注入的整个要点是注入所需的依赖项,而不是来自系统的所有可能的依赖项“以防万一”“需要注入同一组服务的多个位置”——听起来您可以使用抽象基类。“代码最终看起来像:container.DependencyA.DependencyAA.Method(…)
”-看起来您没有很好地隐藏实现。如果希望DependencyA
执行某项操作,为什么需要知道它又有一个DependencyAA
,其中包含要调用的实际方法()?如果你想隐藏一个类的依赖关系的数量,那么依赖性注入是很好的。依赖关系的数量是合理的,但是它往往会导致依赖于注入的依赖性,这是一种反模式。为了解决这个问题,我们可以使用工厂,但在此之前,我们应该考虑到,我们可能已经打破了单一责任原则,这一类可以分裂成几类。使用工厂来减少依赖的数量往往无济于事。您要么注入工厂(在这种情况下注入的依赖项的数量保持不变),要么有效地使用服务定位器——它不会减少依赖项的数量,只是隐藏了它们。您的IContainer
抽象的主要问题是它没有隐藏ClassExample
的复杂性。尽管它可能会消除构造函数过度注入代码的味道,但它并不能解决为什么构造函数过度注入首先会发生的根本问题。最有可能的是,依赖项太多的类太复杂;它违反了单一责任原则。用IContainer
抽象包装依赖项并不会改变这一点。“有多个地方需要注入一组相同的服务”——听起来您可以使用抽象基类。“代码最终看起来像:container.DependencyA.DependencyAA.Method(…)
”-看起来您没有很好地隐藏实现。如果希望DependencyA
执行某项操作,为什么需要知道它又有一个DependencyAA
,其中包含要调用的实际方法()?如果你想隐藏一个类的依赖关系的数量,那么依赖性注入是很好的。依赖关系的数量是合理的,但是它往往会导致依赖于注入的依赖性,这是一种反模式。为了解决这个问题,我们可以使用工厂,但在此之前,我们应该考虑到,我们可能已经打破了单一责任原则,这一类可以分裂成几类。使用工厂来减少依赖的数量往往无济于事。您要么注入工厂(在这种情况下注入的依赖项的数量保持不变),要么有效地使用服务定位器——它不会减少依赖项的数量,只是隐藏了它们。您的IContainer
抽象的主要问题是它没有隐藏ClassExample
的复杂性。尽管它可能会消除构造函数过度注入代码的味道,但它并不能解决为什么构造函数过度注入会在第一个pl中发生的根本问题