最佳做法是在域模型的边缘解析和注入具体类型,然后通过域下载这些类型?例如,让容器将具体类型注入Web应用程序中的MVC控制器构造函数,或基于服务的应用程序中的服务端点?
我对容器对象图形连线的理解有点松懈。
在域中执行等效的Container.Resolve()是否合适?
答案 0 :(得分:6)
DI实际上只是达到目的的手段:松散耦合。这是一种通过将接口(或基类)注入消费者来实现松散耦合的方法,这样您就可以彼此独立地改变它们。
作为一般规则,通过注入具体类型获得的不多。你不能用另一种类型交换类型,因此DI的主要优点就会丢失。
您可能会认为这意味着您只需从消费者中创建具体实例,但更好的选择是从这些类型中提取接口(然后注入它们)
并且没有:永远不适合从域模型中提取容器。那是Service Locator anti-pattern。 好莱坞原则也适用于此:
不要打电话给容器;它会打电话给你
(也就是说,即使是具体的类型,注入它也有一些辅助的好处。如果它是非密封的并且有一个或多个虚拟成员,你仍然可以覆盖它的一些行为,即使它是密封的,如果你注入它,你仍然可以控制它的生命周期 - 例如,你可以在多个消费者之间共享相同的实例。但是,这些好处纯粹是次要的,通常不是我们决定注入任何东西的主要原因。)
另一个问题(以及您似乎实际要问的问题)是注入服务是否适合将其传递给其他服务。不,不是,因为它会违反单一责任原则并导致Constructor Over-Injection。
最好将细粒度服务包含在更粗粒度的服务中。我将这些称为Aggregate Services或抽象外墙。虽然这些本身具有依赖性(如您提到的服务端点),但这些将是实现细节。从顶级消费者的角度来看,它们并不存在。
这不仅可以很好地解决构造函数中过多依赖项的问题,还可以帮助您在应用程序层之间实现更好的隔离。
答案 1 :(得分:2)
查看KrzysztofKoźmic关于这个主题的blog post(s) - 我认为他对此有一些很好的看法,他们几乎总结了当前的“最佳实践”。