我使用 IoC (DI) 方法,通常具有参数,这些参数是由最低层(数据库层等)从配置设置(即连接字符串、静态值等)读取的。最好的方法是什么?
-
直接在这个最底层读取,即:
string sendGridApiKey = ConfigurationManager.AppSettings["SendGridApiKey"];
它可以工作,但还需要将此密钥添加到单元测试项目的配置文件中。另外,汇编依赖于配置文件
- 在最高层(即 Web 应用程序)中读取它并从所有层中作为参数抛出?它会起作用,但是所有中间层都会获取未使用的参数(因此,它们将依赖于未使用的事物)。
当最低层的不同实现可能需要不同的参数时,还存在一个问题。 IE。 SendMail1 可以需要 SMTP/登录名/密码,但 SendMail2 可以仅需要 ApiKey,但 SendMail1 和 SendMail2 应实现相同的接口。因此,使用方法 #2 会产生困难
您概述的两种方法都效果不佳 - 首先(读取服务中的配置)会阻止您提到的单元测试,其次(从顶层传递配置)需要了解顶层每个服务的所有可能实现。
我喜欢依赖 DI 容器对配置存储和为每个接口注册的对象类型的了解的方法:
-
在注册期间传递配置 - 即,如果容器支持注册工厂方法,则此类工厂方法可以读取配置并调用具体服务的特定构造函数
// constructor: publc ConcreteServiceX(int setting1, string setting2)...
container.RegisterFactory<IServiceX>(
container => return new ConcreteServiceX(42, ReadSetting("X"));
-
将容器中每个服务的配置注册为类/接口
// constructor: publc ConcreteServiceX(IConcreteServiceXSettings settings)...
container.RegisterType<IService,ConcreteServiceX>();
container.RegisterInstance<IConcreteServiceXSettings>(
new ConcreteServiceXSettings(42, ReadSetting("X"));
两种方法都将配置系统的知识本地化到一处(容器配置),并允许更轻松地对每个服务(不依赖于配置存储类型)以及更高级别的对象(无需了解服务的任何设置)进行单元测试。
Note: sample use Unity-like syntax, adopt to container of your choice
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)