此问题使用Unity语法,但它适用于所有IOC容器。
如果我有一个带有十几个依赖项的构造函数,那就没什么大不了的了。
Container.RegisterType<ICustomerService, CustomerService>();
稍后我可能需要一个由命名实例填充的构造函数参数。不幸的是,API方法现在变得非常丑陋:
Container.RegisterType<ICustomerService, CustomerService>(new InjectionConstructor(
typeof(ICustomerRepository),
typeof(IEntityMapper),
typeof(IContext),
typeof(IOnboardingValidator),
typeof(ICustomerValidator),
typeof(ICustomerVerifier),
typeof(ICustomerHelper),
new ResolvedParameter<HttpClient>("producer"),
typeof(ILog)));
我可以通过在构造函数参数本身上放置一个[Dependency(&#34; producer&#34;)]注释来避免这种丑陋的冗长,但不幸的是,我的业务程序集将依赖于Unity库,我我试图避免。
如果有一种方法可以告诉Unity(或Autofac,Windsor,SimplerInjector,StructureMap等)使用构造函数中声明的形式参数名称&#34;如果&#34;它表示要注入的命名实例。如果形式参数名称与任何命名绑定都不匹配,则它只是假定使用默认绑定。
这样的事情:
Container.RegisterType<ICustomerService, CustomerService>(new InjectionNameHandler());
也许这对于物业注入也有同样的目的。
上述假设指令省去了必须指定构造函数的每个参数的工作,只需调整单个参数的分辨率。
当然,这假设具体类型中最长的构造函数是我感兴趣的构造函数,但这恰恰是最有用的!
有没有办法在Unity 2中执行此操作? Unity 3?或任何其他IOC容器?
答案 0 :(得分:1)
如果我有一个带有十几个依赖项的构造函数,那就不大了 处理
事实上,这是一个大问题。具有许多依赖项的组件往往违反Single Responsibility Principle(SRP)。 SRP违规导致代码难以测试且难以维护。
如果您将代码重构为多个更简洁的类,问题可能不会完全消失,它已经不是问题了。
我认为您的代码是您违反单一责任原则的一个很好的例子。问题已经从类的名称开始:CustomerService
。 &#39;服务&#39; postfix已经闻起来像是违反了单一责任原则Open/close Principle(OCP)和Interface Segregation Principle(ISP)。您可能违反SRP,因为此类将倾向于容纳许多与客户相关的用例。由单个实体对事物进行分组并不能使它成为一个单一的责任。您将违反OCP,因为每次添加与客户相关的新用例时,您都必须更改此类和界面。 ICustomerService
接口违反ISP,因为它有很多方法,而该接口的消费者只需要一个或两个,但绝不会全部。
除此之外,CustomerServices
课程取决于ILog
和ICustomerValidator
服务。这些似乎是贯穿各领域的关注点,主要阶层不应该关注跨领域的问题。您应该使用面向方面编程(AOP)技术来应用横切关注点,例如拦截或(最好)装饰。
然而,这不可避免地会引导您进行here和here所描述的设计,其中每个用例都有自己的类,并且所有用例都放在相同的通用one-member-abstraction之后。
稍后我可能需要一个构造函数参数填充一个 命名实例
虽然不是一个硬性规则,但我的经验是,组件同时具有配置值和许多依赖关系并不常见。因此,您可能会在此处违反SRP,因为您可能希望将producer
参数抽象出来。
特别是当您谈论的这个HttpClient
是.NET框架类型时,例如System.Net.Http.HttpClient
。在这种情况下,您违反了Dependency Inversion Principle(DIP),因为您不仅依赖于具体类型而不是抽象,它是一个框架组件,但它应该是您的应用程序,应该定义它需要的抽象。
因此,不是注入HttpClient
,而是注入根据您的应用需求量身定制的服务,并遵循SOLID原则。这永远不可能是框架组件,甚至不是框架提供的抽象,因为这样的抽象仍然会违反DIP和ISP。