This topic explains run-time registration of the various interception elements, including interceptors, behaviors, policies, handlers, and matching rules that Unity uses to configure a container for interception. The configuration information is used when creating instances of types for which you want to add interception capabilities to change the behavior of that object or type. In order to provide backward compatibility, Unity 2.0 supports calling the older API SetInterceptorFor and SetDefaultInterceptorFor methods on the Interception container extension in addition to supporting the Unity 2.0 approach using the RegisterType API to explicitly configure interceptors, behaviors, and additional interfaces.
- Registering Interceptors and Interceptor Behaviors Explicitly Using RegisterType
- Default Interceptor for a Type
- Registering Additional Interface
- Registering Policy Injection Components
For information on using a configuration file to configure a container for interception, see Configuration Files for Interception.
For information on the design of Unity interception see Interception with Unity.
For information on using interception without a dependency injection (DI) container, see the "Stand Alone Unity Interception" section in Using Interception in Applications.
Registering Interceptors and Interceptor Behaviors Explicitly Using RegisterType
Unity 2.0 enables interception like any other container extension by using container.AddNewExtension. Then you can configure a type for interception using an interceptor of your choosing, with behaviors of your choosing. In Unity 2.0 you explicitly configure which object is to be intercepted by which interception mechanism and specify the behavior by using InterceptionBehavior; Unity 1.2 implicitly set up policy injection when you configured an interceptor. The following example shows how to configure interception for a type and turn on a custom behavior. This example first adds the Interception extension by calling AddNewExtension, and then uses RegisterType to register a VirtualMethodInterceptor and an interception behavior. The behavior must be defined elsewhere.
IUnityContainer container = new UnityContainer(); container.AddNewExtension<Interception>(); container.RegisterType<TypeToIntercept>( new Interceptor<VirtualMethodInterceptor>(), new InterceptionBehavior<CustomBehavior>());
Using this overload of the Interceptor constructor actually tells the container to resolve the interceptor through the container. You can pass an optional string, which becomes the name to resolve with. In most applications you would simply leave this blank, but if you have implemented custom interceptors, you might want to provide additional configuration. There is another overload of the Interceptor constructor you can use to specify the interceptors and behaviors by creating instances and passing the actual instances into the container, as done in the following example:
// Add the interception extension to the container IUnityContainer container = new UnityContainer(); container.AddNewExtension<Interception>(); // Configure interception container.RegisterType<IInterface, BaseClass>( "myInterceptor", new Interceptor(new InterfaceInterceptor()), new InterceptionBehavior(new CustomBehavior()), new InterceptionBehavior(new SomeOtherBehavior()));
When using multiple named registrations for the same type, you often want all implementations of that type to be intercepted. Rather than requiring you to specify the interceptor for all registrations, you can instead specify a default interceptor on any one of the registrations. This interceptor will be applied any time that type is resolved, regardless of the name used to resolve it. Additionally, you can also provide default interception behaviors, which apply the behaviors to all instances of that type regardless of the instance name.
// Add the interception extension to the container IUnityContainer container = new UnityContainer(); container.AddNewExtension<Interception>(); // Configure default interception for BaseClass container.RegisterType<IInterface>( new DefaultInterceptor<InterfaceInterceptor>(), new DefaultInterceptionBehavior(new CustomBehavior()), new DefaultInterceptionBehavior(new SomeOtherBehavior()); // Configure type mappings container.RegisterType<IInterface, BaseClass>("myInterceptor") .RegisterType<IInterface, OtherClass>("interceptedToo");
Visit MSDN for information on how previous versions of Unity provided Configuration Support for Interception.
Registering Additional Interfaces
The interception mechanism can add entirely new interfaces to objects. The interfaces are implemented by the interception behaviors. In most cases, the behaviors themselves provide the information about which additional interfaces they implement. In rare cases such as for a mock object behavior, the behavior can implement any interface, so extra information is required about exactly which extra interfaces to add to the object.
The InterceptionExtension.AdditionalInterface class enables you to implement additional interfaces on target objects. It contains information for additional interfaces that will be added to the intercepted object and configures a container accordingly.
In the following example, IOtherInterface is an AdditionalInterface interface that configures the interceptor to implement a specified interface in addition to the original interfaces implemented by the target object, and MyInterceptionBehavior is an implementation of the IInterceptionBehavior interface which defines an interception behavior.
IUnityContainer container = new UnityContainer(); container.RegisterType<IInterface, BaseClass>( "sample", new Interceptor<VirtualMethodInterceptor>(), new AdditionalInterface<IOtherInterface>(), new InterceptionBehavior<MyInterceptionBehavior>());
For information on using a configuration file to configure interception for additional interfaces see Configuration Files for Interception.