我是一个DI新手,所以请原谅我,如果这是一个错误的方法或一个愚蠢的问题。
假设我有一个创建/更新订单的表单,我知道它需要检索要显示的产品和客户列表。我想传递它正在编辑的Order对象,但我也想将ProductsService和CustomersService作为依赖项注入。
所以我希望我的IoC容器(无论我使用哪个容器)提供服务,但是由调用代码来提供Order对象进行编辑。
我是否应该将构造函数声明为将Order对象作为第一个参数以及之后的ProductsService和CustomersService,例如:
public OrderForm(Order order, ProductsService prodsSvc, CustomersService custsSvc)
...或者依赖性应该是第一个,Order对象是最后的,例如:
public OrderForm(ProductsService prodsSvc, CustomersService custsSvc, Order order)
重要吗?它取决于我使用的IoC容器吗?还是有“更好”的方式?
答案 0 :(得分:5)
马特,你不应该将普通参数与依赖项混合在一起。由于您的对象将在IoC容器的内部创建,您如何指定必要的参数?
混合依赖和普通参数会使程序的逻辑变得更复杂。
在这种情况下,最好在IoC构造 OrderForm 之后声明依赖项属性(即从构造函数中删除依赖项)或初始化 order 字段并解析它的依赖项(即删除构造函数中的常规参数。)
此外,您可以声明所有参数,包括订单作为依赖项。
答案 1 :(得分:4)
我不同意@ aku的回答。
我认为你正在做的事情很好,而且还有其他方法可以做到这一点,或多或少是正确的。例如,人们可能会质疑这个对象是否应该首先依赖于服务。
无论DI如何,我觉得至少在每个对象拥有的状态中澄清是有帮助的,例如真实状态(Order),派生状态(如果有)和依赖(服务):< / p>
http://tech.puredanger.com/2007/09/18/spelunking/
在任何构造函数或方法上,我更喜欢先传递真实数据,最后传递依赖项或外部资源。所以在你的例子中,我更喜欢第一个。
答案 2 :(得分:3)
对于允许实例化OrderForm实例而没有对Order实例的必需引用,我感到有点不安。一个原因可能是这会阻止我对空订单进行前期检查。还有什么进一步的想法吗?
我想我可以放心地知道OrderForm对象只能通过Factory方法实例化,以确保在调用IoC框架后设置Order属性。
答案 3 :(得分:0)
我参加聚会有点晚了,但是在这种情况下,我建议使用工厂:工厂构造函数将采用所需的*Service
依赖项,DI系统将解析并注入这些依赖项,而{{1} 1}}方法将接受任何其他状态参数-如Build()
。当然,工厂将在DI系统中注册自己,并且可以很好地发挥作用。
Order