Introduction
Part 3 of this series of articles described the different types of dependency injection that we can use in general. These are setter injection, constructor injection and interface injection.
part3 介绍了我们通常可以依赖注入的几种类型setter injection,constructor injection,interface injection
Part 5 showed how dependency injection works in the CAB. The examples given there exclusively used setter injection. In general we don’t use interface injection in CAB projects, but we can use constructor injection. This short article will show you how.
part5 告诉我们 dependency injection 是怎么work的, 我们讲的那个示例用的是setter injection,通常情况下 我们不在CAB projects 使用interface injection,但是我们可以使用constructor injection,这篇短文将告诉你怎样做
Constructor Injection Example
As is fairly obvious, constructor injection injects your dependencies in a constructor rather than a setter. To do this in the CAB we once again use attributes.
constructor injection 通过构造器而不是setter 实现注入, 我们再次使用attribute来实现这点。
We can return to our original example of setter injection and rework it to use constructor injection. To do this we add a constructor to our Component2 class as below, and we remove the setters we were using previously (they are commented out below):
我们回到之前的例子,将其改成constructor injection,我们将构造器加入到我们的Component2 ,且将之前的setter删除掉。
public class Component2 { private Component1 component11; [InjectionConstructor] public Component2([ComponentDependency("FirstComponent1")]Component1 component, [CreateNew]Component1 component2) { component11 = component; component12 = component2; } }
The constructor will inject the same dependencies as the setters did previously if we create Component2 with the AddNew method of a WorkItem’s Items collection as below:
构造器会通过AddNew 方法像之前setter一样注入相同的依赖。
RootWorkItem.Items.AddNew<Component2>("Component2");
When the CAB creates a component with AddNew it looks for a constructor decorated with the InjectionConstructor attribute. If it finds one it calls that constructor, and injects dependencies via the constructor parameters as shown. It applies the usual rules if any of the constructor parameters are decorated with the CreateNew, ServiceDependency or ComponentDependency attributes.
当CAB AddNew 创建一个component 的时候, 它搜索构造器的装饰:InjectionConstructor ,如果能找到它就会调用并且注入参数里的依赖,其他的CreateNew, ServiceDependency or ComponentDependency attributes.也同样使用相同的规则。
The code for this example is available.
Constructor Injection Issues
Note that if there’s only one constructor in the class you don’t actually need the InjectionConstructor attribute. The CAB assumes you mean to use that one constructor as the injection constructor. Our example above will work without the attribute. If you have more than one constructor in the class you do need the attribute, and in general it’s probably good practice to include the attribute if you are using constructor injection.
注意如果这个class只有一个构造器,你实际上不需要加入 InjectionConstructor attribute, The CAB 会认为ini使用那个构造器作为注入构造器。我们上面的例子在没有这个attribute的情况下,同样work。如果你在同一个类中有许多构造器,你确实需要这个attribute,通常情况下最好还是加上这个attribute如果你确实想使用构造器注入。
Note also that in the original example in part 5 we created the Component2 instance with a standard ‘new’ keyword and then added it to the items collection:
注意在part5原有的例子里我们通过 ‘new’ 创建了Component2 的实例,然后将此加入到items collection里
Component2 component2 = new Component2(); RootWorkItem.Items.Add(component2);
If we do this with our new Component2 the injection will not work. In fact the code won’t even compile as we no longer have a constructor that doesn’t take any arguments. Even if we put a constructor with no arguments into Component2 we’re clearly not going to get any dependency injection as we are not creating the component with the CAB and the standard ‘new’ keyword doesn’t know how to do constructor injection.
如果我们现在再这样做,注入将不会实现,事实上编译都不会通过,因为我们已经不再有没有参数的构造器了,即使我们放置了一个没有参数的构造器, 我们明显也不会得到任何注入 因为我们用new创建的实体不知道如何去做这个构造器注入。
Finally it’s worth noting that if you don’t put any attribute on an argument of an injection constructor the CAB treats it as if it had a ServiceDependency attribute. That is, it tries to inject a service of the appropriate type. If there’s no such service it creates a new one and adds it to the Services collection. This is NOT the behaviour you get with the ServiceDependency attribute: if you apply the ServiceDependency attribute and there’s no such service you get a ServiceMissingException when you try to create the new object.
最后如果你不在一个构造器注上里的任何参数上放置任何attribute,cab会认为他有一个ServiceDependency 的属性,他会试着注入一个合适的service ,如果没有这样的service ,他会新建一个,并把他放入到Services collection里,这和ServiceDependency attribute的作用不一样,如果你应用了一个ServiceDependency attribute 但是却没有这样的service 它将会报这样一个错ServiceMissingException
Setter Injection vs Constructor Injection
Whether you use setter injection or constructor injection is really a personal choice. There isn’t much to choose between them in terms of functionality. As we’ve seen if you create your object with the ‘new’ keyword initially and then add it to a CAB collection you can’t use constructor injection. Also arguably the syntax for the constructors is a little cumbersome. But normally your CAB objects will be created and added to CAB collections with the AddNew keyword or something equivalent. In this case both setter injection and constructor injection inject the dependencies on creation of the object, and the two types of injection are functionally equivalent.
你使用setter injection 还是constructor injection完全是你个人的选择, 在功能上两者没什么差别, 正如我们所看到的那样,如果你用new新建一个对象,并将其加入到cab collection里,你不能使用 构造器注入,而且constructors 的语法也也有点奇怪,但是通常情况下你的 CAB objects 会被创建,并且通过AddNew 加入到CAB collections ,在这种情况下这两种情况完全相同。
Conclusion
We’ve now covered dependency injection in the CAB in some detail. Part 7 of this series will discuss services in the CAB.
我们现在讨论了一些dependency injection的细节, 我们会在part7里讨论services