在Unity中解析类型时传递构造函数参数:最佳实践

时间:2010-01-28 11:26:44

标签: c# .net dependency-injection unity-container

有时需要使用依赖注入来提供在构造函数中使用的参数。这是Unity(以及其他依赖注入容器)支持的内容,因此当它尝试创建该类型的实例时,它可以将您的参数作为参数提供给构造函数。

我的问题是:这种方法是否可取?

在接口中,无法指定实现类必须具有的参数。通过为Unity指定参数,您假设实现类具有这些参数,并且您将对未来的实现类放置隐式约束。这些约束无法通过界面传达。

那么,这是如何指定接口本身(在.NET中)的缺陷,例如。应该可以指定构造函数签名吗?或者由于某些其他需要,此功能(能够提供构造函数参数)已包含在Unity中吗?

唯一真正可行的方法(对我而言)似乎是使用工厂来创建实现类,并在工厂进行依赖注入。

我很感激我的问题可能不太清楚,所以我会稍微区别一点:在一个有构造函数需要参数的类上进行依赖注入的最佳方法是什么?

(我不认为这个问题是主观的,因为这种类型的依赖注入可能只有一个设计模式。)

编辑:

我应该补充一点,我的主要问题是我可以创建一个新的实现类,它具有额外的构造函数参数(其中构造函数参数不是可以由unity创建的东西)。

3 个答案:

答案 0 :(得分:2)

我不确定你在哪里认为构造函数注入不适合DI。我会说实际情况与此相反:构造函数注入是用于实现依赖注入的最常见模式之一 - 我会说它是最常见的 模式,并且该视图肯定得到以下事实的支持:大多数控制反转容器(DI容器)使用构造函数注入作为其首选机制。

例如,StructureMap有一个核心的,非常具体的构造函数注入支持,它将选择具有最多参数的构造函数作为用于依赖项解析的构造函数。

使用构造函数注入模式所说的是“我通过将它们指定为传递给构造函数的参数来删除类中的硬编码依赖项 - 我的类在没有这些依赖项的情况下无法实例化”。当然,该陈述的前半部分是DI的本质,但是后半部分更强调了这一点。

依赖关系是一个应该能够轻松更改的实现细节,提供灵活,松散耦合的解决方案。他们是关于如何,而不是什么。接口指定了什么。所以我要说你在接口中指定依赖关系的建议实际上违背了依赖注入的概念。

至于你关于工厂的陈述 - 这正是IOC容器所代表的 - 伟大的大工厂负责解决方案的依赖树,所以你不需要关心。

修改

我想也许您在询问是否要提供非依赖构造函数参数的情况,例如引用实体的id或初始状态枚举?

我个人认为IOC容器没有问题。它仍然是你的类的初始状态,因此需要明确表达创建该状态的规则。这可能意味着您有时需要更多您可能喜欢的IOC容器参考,但放弃结构注射的其他好处并不是一个非常可怕的情况。

答案 1 :(得分:0)

IoC容器(比如Unity)的职责是将接口与具体实现连接起来。这意味着您的容器必须知道接口以及如何创建实现接口的对象。使用构造函数注入是完全合法的,也是推荐的方法。当您的应用程序通过Resolve()方法请求接口时,Unity将创建具体实现。 Unity容器本身是创建对象的工厂,您使用Unity是因为您不想自己实现这些工厂。

答案 2 :(得分:0)

这里的问题是Unity中的InjectionConstructor的定义vs在Castle.Windsor中的定义。

在Unity中,如果你需要注入一个特定的参数,比如AppSetting,你也被迫提供所有其他参数,从而修复了构造函数的签名。但是,在Castle.Windsor中,它采用您提供的参数,然后使用解析机制以正常方式定位其他参数。

有可能通过编写一个自定义的构建器策略将其引入Unity,该策略可以实现最佳匹配"使用构造函数的方法而不是默认的贪婪/提供默认的所有内容。