在阅读了Mark Seemann关于依赖注入的书之后,我很激动地将我的团队从服务定位器反模式转移到更优雅的解决方案中,我的代码中没有出现我的DI。虽然我们有一个界面可以将我们与我们选择的DI容器分离,但我总觉得我们过于依赖容器而且 - 同时 - 无法充分利用它并且我看到很多很好的理由转向构造函数注入+抽象工厂模式。
我的问题与政策和程序有关:我们尝试遵循SOLID和相关原则到T.我们还将我们的类标记为内部密封,除非他们有(明显的)理由不是。这在过去总是很好,因为它阻止我们违反我们的“代码到接口”的理念,因为所有在程序集边界上可见的都是接口,只能通过我们的容器获得。
在练习Mark Seemann的建议时,我发现我的课程需要公开,以便组合根能够将所需的组件组合在一起。在构建一个不应该假设其引用代码将使用容器的共享库时尤其如此,特别是它的容器味道。
在构建从一个程序集的对象映射到另一个程序集的映射器时,我也得出了这个结论。例如,我可能有一个Models.Interfaces层,Business和Repository层使用它来来回传递数据。之前,我们只需要在Models.Interfaces中创建一个实现契约的程序集,Business和Repository都会在需要Model.Interface的新实例时使用服务定位器。没有服务定位器,似乎我唯一的选择是删除模型接口,或者在同一个项目中实现我的Model.Interfaces,允许Business / Repository根据需要新建实例。
除了性能之外,我想知道在Model.Interfaces项目中是否有公共模型实现是一种设计气味,我想知道内部密封类是否可以与DI的这种方法一致,以及我是否在编码到接口和使用构造函数注入+抽象工厂DI模式时,我遗漏了一些东西。
答案 0 :(得分:0)
一个解决方案 - 有自己的问题,见下文 - 可能是将您的组合代码放在一个单独的程序集X中,然后通过{{3允许该程序集访问其他程序集的internal
类型在X的那些程序集中指定。
一个明显的缺点是,如果稍后在不同的应用程序中重新使用程序集,则必须为程序集的组合根组件Y添加另一个[assembly: InternalsVisibleTo("Y")]
属性。
我怀疑依赖[assembly: InternalsVisibleTo]
的丑陋与首先制定实施类型internal
所获得的假设优势相抵消:毕竟,您的internal sealed
实施类型是不只是在内部使用,所以也许它们应该是public sealed
。
我不认为实现public
本身会破坏DI原则 - 至少不完全。例如,当有多个可供选择的接口实现时,抽象工厂仍然可以帮助您减少代码中选择和正确初始化实现的需求。
答案 1 :(得分:0)
如果没有明确的方向,我决定维持我当前的架构,即只有一个Interfaces层,这是另外两层之间的通信契约。我创建了一个单独的IModelFactory接口(就像一个迷你服务定位器精简版),我需要能够从任一层完成每个模型的Create()方法。然后我将这个接口注入到每个层中,这样他们就可以在不使用外部依赖项的new关键字的情况下创建DTO。