Annotating Objects for Constructor Injection
Retired Content |
---|
This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. |
The latest Enterprise Library information can be found at the Enterprise Library site. |
The Unity Application Block supports automatic dependency injection and dependency injection specified through attributes applied to members of the target class. You can use the Unity container to generate instances of dependent objects and wire up the target class with these instances.
Typical Goals
In this scenario, you use both the automatic constructor injection mechanism and an attribute applied to the constructor of a class to define the dependency injection requirements of that class. The attribute can also specify parameters that the constructor will pass to the dependent object that the container generates.
Solution
To perform injection of dependent classes into objects you create through the Unity container, you can use the following two techniques:
- Single-constructor automatic injection. With this technique, you allow the Unity container to satisfy any constructor dependencies defined in parameters of the constructor automatically. You use this technique when there is a single constructor in the target class.
- Multiple-constructor injection using an attribute. With this technique, you apply attributes to the class constructor(s) that specify the dependencies. You use this technique when there is more than one constructor in the target class.
Constructor injection is a form of mandatory injection of dependent objects, provided developers use the Unity container to generate the target object. The dependent object instance is generated when the Unity container creates an instance of the target class using the constructor.
For more information, see Notes on Using Constructor Injection.
Single-Constructor Automatic Injection
For automatic constructor injection, you simply specify as parameters of the constructor the dependent object types. You can specify the concrete type, or specify an interface or base class for which the Unity container contains a registered mapping.
To use automatic single-constructor injection to create dependent objects
- Define a constructor in the target class that takes as a parameter the concrete type of the dependent class. For example, the following code shows a target class named MyObject containing a constructor that has a dependency on a class named MyDependentClass.
- In your run-time code, use the Resolve method of the container to create an instance of the target class. The Unity container will instantiate the dependent concrete class and inject it into the target class. For example, the following code shows how you can instantiate the example target class named MyObject containing a constructor that has a dependency on a class named MyDependentClass.
- Alternatively, you can define a target class that contains more than one dependency defined in constructor parameters. The Unity container will instantiate and inject an instance of each one. For example, the following code shows a target class named MyObject containing a constructor that has dependencies on two classes named DependentClassA and DependentClassB.
- In your run-time code, use the Resolve method of the container to create an instance of the target class. The Unity container will create an instance of each of the dependent concrete classes and inject them into the target class. For example, the following code shows how you can instantiate the example target class named MyObject containing a constructor that has constructor dependencies.
- In addition to using concrete types as parameters of the target object constructor, you can use interfaces or base class types and then register mappings in the Unity container to translate these types into the correct concrete types. Define a constructor in the target class that takes as parameters the interface or base types of the dependent class. For example, the following code shows a target class named MyObject containing a constructor that has a dependency on a class that implements the interface named IMyInterface and a class that inherits from MyBaseClass.
- In your run-time code, register the mappings you require for the interface and base class types, and then use the Resolve method of the container to create an instance of the target class. The Unity container will instantiate an instance of each of the mapped concrete types for the dependent classes and inject them into the target class. For example, the following code shows how you can instantiate the example target class named MyObject containing a constructor that has a dependency on the two objects of type IMyInterface and MyBaseClass.
Multiple-Constructor Injection Using an Attribute
When a target class contains more than one constructor with the same number of parameters, you must apply the InjectionConstructor attribute to the constructor that the Unity container will use to indicate which constructor the container should use. As with automatic constructor injection, you can specify the constructor parameters as a concrete type, or you can specify an interface or base class for which the Unity container contains a registered mapping.
To use attributed constructor injection when there is more than one constructor
- Apply the InjectionConstructor attribute to the constructor in the target class that you want the container to use. In the simplest case, the target constructor takes as a parameter the concrete type of the dependent class. For example, the following code shows a target class named MyObject containing two constructors, one of which has a dependency on a class named MyDependentClass and has the InjectionConstructor attribute applied.
- In your run-time code, use the Resolve method of the container to create an instance of the target class. The Unity container will instantiate the dependent concrete class defined in the attributed constructor and inject it into the target class. For example, the following code shows how you can instantiate the example target class named MyObject containing an attributed constructor that has a dependency on a class named MyDependentClass.
- Alternatively, you can define a multiple-constructor target class that contains more than one dependency defined in the target constructor parameters. The Unity container will instantiate and inject an instance of each one. For example, the following code shows a target class named MyObject containing an attributed constructor that has dependencies on two classes named DependentClassA and DependentClassB.
- In your run-time code, use the Resolve method of the container to create an instance of the target class. The Unity container will create an instance of each of the dependent concrete classes defined in the attributed constructor and inject them into the target class. For example, the following code shows how you can instantiate the example target class named MyObject containing a constructor that has constructor dependencies
- In addition to using concrete types as parameters of the target object constructor, you can use interfaces or base class types, and then register mappings in the Unity container to translate these types into the correct concrete types. For details, see steps 5 and 6 of the procedure Single-Constructor Automatic Injection.
Notes on Using Constructor Injection
The following notes will help you to get the most benefit from using constructor injection with the Unity Application Block.
How Unity Resolves Target Constructors and Parameters
When a target class contains more than one constructor, Unity will use the one that has the InjectionConstructor attribute applied. If there is more than one constructor, and none carries the InjectionConstructor attribute, Unity will use the constructor with the most parameters. If there is more than one such constructor (more than one of the "longest" with the same number of parameters), Unity will raise an exception.
Constructor Injection with Existing Objects
If you use the RegisterInstance method to register an existing object, constructor injection does not take place on that object because it has already been created outside of the influence of the Unity container. Even if you call the BuildUp method of the container and pass it the existing object, constructor injection will never take place because the constructor will not execute. Instead, mark the constructor parameter containing the object you want to inject with the Dependency attribute to force property injection to take place on that object, and then call the BuildUp method. This is a similar process to property (setter) injection. It ensures that the dependent object can generate any dependent objects it requires. For more details, see Annotating Objects for Property (Setter) Injection.
Avoiding Circular References
Dependency injection mechanisms can cause application errors if there are circular references between objects that the container will create. For more details, see Circular References with Dependency Injection.
When to Use Constructor Injection
You should consider using constructor injection in the following situations:
- You want to instantiate dependent objects automatically when your instantiate the parent object.
- You want a simple approach that makes it easy to see in the code what the dependencies are for each class.
- The parent object does not require a large number of constructors that forward to each other.
- The parent object constructors do not require a large number of parameters.
- You want to be able to hide field values from view in the application code by not exposing them as properties or methods.
- You want to control which objects are injected by editing the code of the dependent object instead of the parent object or application.
If you are not sure which type of injection to use, the recommendation is that you use constructor injection. This is likely to satisfy almost all general requirements.
Note
You can also apply constructor injection dynamically using the configuration API of the Unity container. For more information, see the section "Dynamically Configuring Constructor, Property, and Method Injection" in the topic Entering Configuration Information.
More Information
For more information on the techniques discussed in this scenario, see the following topics: