C# 尝试应用良好的依赖项注入实践时遇到的问题
我已经在.NET中使用IoC(主要是Unity)和依赖注入有一段时间了,我非常喜欢这种模式,它可以鼓励创建松散耦合的软件类,并且应该更容易隔离以进行测试 我通常尝试坚持的方法是——特别是不注入容器本身,而只使用构造函数注入,这样您就可以从构造函数签名中清楚地看到类的所有依赖项。确实在这里有一个帐户,但我不确定他是否仍然活跃 不管怎么说,当我最终违反了其他法律之一,或者最终得到了一些感觉不对劲或看起来不对劲的东西时,我不得不质疑我是否遗漏了一些东西,是否可以做得更好,或者干脆不应该在某些情况下使用国际奥委会。考虑到这一点,这里有一些例子,如果您能提供一些建议或进一步讨论,我将不胜感激:C# 尝试应用良好的依赖项注入实践时遇到的问题,c#,.net,design-patterns,dependency-injection,C#,.net,Design Patterns,Dependency Injection,我已经在.NET中使用IoC(主要是Unity)和依赖注入有一段时间了,我非常喜欢这种模式,它可以鼓励创建松散耦合的软件类,并且应该更容易隔离以进行测试 我通常尝试坚持的方法是——特别是不注入容器本身,而只使用构造函数注入,这样您就可以从构造函数签名中清楚地看到类的所有依赖项。确实在这里有一个帐户,但我不确定他是否仍然活跃 不管怎么说,当我最终违反了其他法律之一,或者最终得到了一些感觉不对劲或看起来不对劲的东西时,我不得不质疑我是否遗漏了一些东西,是否可以做得更好,或者干脆不应该在某些情况下使用
- a) 在一个大型应用程序中,我总是发现我需要3个依赖项来访问基础设施(例如日志记录、配置、持久性),然后才能获得类完成其(希望是单一职责)工作所需的特定依赖项。我知道有一种方法可以将这些依赖项组重构并打包成一个独立的依赖项组,但我经常发现这只是其他几个服务的一个门面,而不是自己承担任何真正的责任。在本规则的上下文中,是否可以忽略某些基础结构依赖项,前提是类仍被视为具有单一责任
- b) 重构会加剧这个问题。考虑一个非常普通的任务,就是打破一个有点大的类——你把一个功能区移到一个新的类中,第一个类就依赖于它。假设第一个类仍然需要它以前拥有的所有依赖项,那么它现在有一个额外的依赖项。在这种情况下,我可能不介意这个依赖关系更紧密地耦合,但让容器提供它(与使用new…())相比)更整洁,即使新依赖关系没有自己的接口,它也可以这样做
- c) 在一个特定的示例中,我有一个类负责每隔几分钟在系统中运行各种不同的函数。由于所有函数都正确地属于不同的区域,所以这个类最终有许多依赖项,以便能够执行每个函数。我猜在这种情况下,应该考虑其他方法,可能涉及事件,但到目前为止,我还没有尝试这样做,因为我想协调任务运行的顺序,在某些情况下,应用逻辑,包括过程中的结果
让我回答问题3。让单例依赖于瞬态是容器探查器试图检测和警告的问题。服务应该只依赖于生命周期大于或等于其自身生命周期的其他服务。注入工厂接口或委托来解决这个问题通常是一个好的解决方案,而传入容器本身则是一个坏的解决方案,因为您最终得到的是 您可以通过实现代理来解决这个问题,而不是注入工厂。下面是一个例子:
public interface ITransientDependency
{
void SomeAction();
}
public class Implementation : ITransientDependency
{
public SomeAction() { ... }
}
使用此定义,可以基于ITransientDependency
在中定义代理类:
public class TransientDependencyProxy<T> : ITransientDependency
where T : ITransientDependency
{
private readonly UnityContainer container;
public TransientDependencyProxy(UnityContainer container)
{
this.container = container;
}
public SomeAction()
{
this.container.Resolve<T>().SomeAction();
}
}
公共类TransientDependencyProxy:ITransientDependency
其中T:ITransientDependency
{
私有只读UnityContainer容器;
公共临时依赖CyProxy(UnityContainer容器)
{
this.container=容器;
}
公共行动
{
this.container.Resolve().SomeAction();
}
}
现在,您可以将此TransientDependencyProxy
注册为singleton:
container.RegisterType<ITransientDependency,
TransientDependencyProxy<Implementation>>(
new ContainerControlledLifetimeManager());
container.RegisterType(
新的ContainerControlled LifetimeManager());
虽然它注册为singleton,但它仍将作为瞬态,因为它将把调用转发给瞬态实现
通过这种方式,您可以完全隐藏ITransientDependency
需要是应用程序其余部分的瞬态
如果许多不同的服务类型都需要这种行为,那么定义p将变得很麻烦