使用形式参数名称注入

时间:2015-05-12 02:14:29

标签: c# dependency-injection inversion-of-control ioc-container

此问题使用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容器?

1 个答案:

答案 0 :(得分:1)

  

如果我有一个带有十几个依赖项的构造函数,那就不大了   处理

事实上,这是一个大问题。具有许多依赖项的组件往往违反Single Responsibility Principle(SRP)。 SRP违规导致代码难以测试且难以维护。

如果您将代码重构为多个更简洁的类,问题可能不会完全消失,它已经不是问题了。

我认为您的代码是您违反单一责任原则的一个很好的例子。问题已经从类的名称开始:CustomerService。 &#39;服务&#39; postfix已经闻起来像是违反了单一责任原则Open/close Principle(OCP)和Interface Segregation Principle(ISP)。您可能违反SRP,因为此类将倾向于容纳许多与客户相关的用例。由单个实体对事物进行分组并不能使它成为一个单一的责任。您将违反OCP,因为每次添加与客户相关的新用例时,您都必须更改此类和界面。 ICustomerService接口违反ISP,因为它有很多方法,而该接口的消费者只需要一个或两个,但绝不会全部。

除此之外,CustomerServices课程取决于ILogICustomerValidator服务。这些似乎是贯穿各领域的关注点,主要阶层不应该关注跨领域的问题。您应该使用面向方面编程(AOP)技术来应用横切关注点,例如拦截或(最好)装饰。

然而,这不可避免地会引导您进行herehere所描述的设计,其中每个用例都有自己的类,并且所有用例都放在相同的通用one-member-abstraction之后。

  

稍后我可能需要一个构造函数参数填充一个   命名实例

虽然不是一个硬性规则,但我的经验是,组件同时具有配置值和许多依赖关系并不常见。因此,您可能会在此处违反SRP,因为您可能希望将producer参数抽象出来。

特别是当您谈论的这个HttpClient是.NET框架类型时,例如System.Net.Http.HttpClient。在这种情况下,您违反了Dependency Inversion Principle(DIP),因为您不仅依赖于具体类型而不是抽象,它是一个框架组件,但它应该是您的应用程序,应该定义它需要的抽象。

因此,不是注入HttpClient,而是注入根据您的应用需求量身定制的服务,并遵循SOLID原则。这永远不可能是框架组件,甚至不是框架提供的抽象,因为这样的抽象仍然会违反DIP和ISP。