楼梯模式实施

我在“自适应代码通过C#”一书中遇到了“Stairway”模式描述,我真的不明白这是如何实现的:

楼梯图案 ( 来源 )

所以我有客户端组装:

using ServiceInterface; namespace Client { class Program { static void Main(string[] args) { // Have to create service implementation somehow // Where does ServiceFactory belong? ServiceFactory serviceFactory = new ServiceFactory(); IService service = serviceFactory.CreateService(); service.Do(); } } } 

服务接口组件:

 namespace Service { public interface IService { void Do(); } } 

和服务实现程序集:

 using ServiceInterface; namespace ServiceImplementation { public class PrintService : IService { public void Do() { Console.WriteLine("Some work done"); } } } 

问题是:如何在Client命名空间中获取IService对象? 我应该在哪里放置实际的new PrintService()对象? 这不能是ServiceInterface的一部分,因为接口程序集不依赖于ServiceImplementation 。 但它也不能成为ClientServiceImplementation的一部分,因为Client应该只依赖于ServiceInterface

我遇到的唯一解决方案是在它上面安装Application集,它引用了所有三个( ClientServiceInterfaceServiceImplementation )并将IService注入Client 。 我错过了什么吗?

应用入口点应该是组合根,根据Mark Seemann关于dependency injection的优秀书籍。 在这里,问题更多的是关于依赖性倒置,客户端和实现都应该依赖于抽象。

这个图表没有显示,但希望本书的其他部分明确指出,入口点自然而且必然会引用构建你的解析根源(控制器,服务等)所需的一切 。但这是唯一拥有这种知识的地方。

请记住,客户端有时可以“拥有”它们所依赖的接口:接口ISecurityService可能存在于Controllers程序IUserRepositoryIUserRepository可能存在于ServiceImplementations程序集中,依此类推。 当然,当> 1客户端需要访问接口时,这是不切实际的。

如果您遵循SOLID,您自然会发现dependency injection是必需的,但控制反转容器不是优先考虑的事情。 我发现自己越来越多地使用Pure Dependency Injection(手动构建解析根)。

在这种情况下, Client项目应包含对ServiceServiceImplementation引用。 这些引用仅用于创建将用作DI的IoC容器。 在应用程序启动时,您需要在IoC容器中注册所有接口实现。

如果您将针对Service接口实现ServiceImplementation ,并且您将基于Service intereface对Client进行编码,那么将不依赖于ServiceImplementation

您还可以在“自适应代码通过C#”的示例中看到如何实现Stairway模式:

https://github.com/garymcleanhall/AdaptiveCode/tree/master/Sprints/sample-sprint2-markdown

我会把它放在ServiceFactory 。 您需要一些参数,例如在工厂构造函数中传递或从配置等中检索,这些参数确定工厂创建的IService实现。