Contents tagged with AOP
OK, sixth post on this series, long overdue. You will find the fifth (Injecting Values) here, the fourth (Extensions) here, the third (Aspect-Oriented Programming) here, the second (Dependency Injection) here and the first one (Introduction) here.
This time I’m going to talk about something that came out in Unity 3, automatic (or convention-based) registration of components.
Normally, you register your components by using one of the Register* methods declared in IUnityContainer. The problem is that this has to be done explicitly for each component. Well, since Unity 3, we now have an automatic, convention-based mechanism.
The automatic configuration has two options:
- Using the RegisterTypes method overload that takes several parameters: one for each type to map, a delegate for choosing the registration keys, a delegate for choosing the name of the registration and finally another one for selecting the lifetime manager;
So, here’s an example of the first approach:
This will map all of the types that implement interfaces in the current assembly from their interfaces, provided they belong to the same assembly of their implementation, with a name equal to the implementation type and with a lifetime of singleton.
A more sensible approach, however, might be instead:
This has the following advantage: maps the first found implementation with an empty name, and the others with a name equal to the implementation type.
A RegistrationConvention class could be like this:
And its registration:
Obviously, this approach is more reusable, the same convention class can be carried over to different projects.
One thing worth mentioning: if you specify a lifetime manager, anyone other than null, each registered type will be mapped to itself, besides to its interfaces. For example, a class MyService that implements IMyService will be mapped both as IMyService –> MyService and MyService –> MyService. This is by design.
And that’s it for automatic configurations. Now it’s up to you to customize how you want things to be registered: name of the registration, lifetime, etc.
Stay tuned for more on Unity soon!
Updated on May 7th
Aspect Oriented Programming (AOP) is a technique for applying cross-cutting concerns to existing implementations, without modifying them. Some examples of it are:
- Wrapping method calls that go to the database in transactions automatically;
- Logging all calls to some method, including the input parameters and return value;
- Catching exceptions thrown in a method automatically and doing something with them.
AOP is supported in the Enterprise Library (of which Unity is part) by the Policy Injection application block, and it can be integrated with Unity. You must install this application block, perhaps by using NuGet:
We need to add the interception behavior – which is the one that actually applies aspects – to Unity, either by code:
Or by XML configuration:
Having said that, the first concept we need to know is that of an interceptor. An interceptor in the Policy Injection block is an implementation of Microsoft.Practices.Unity.InterceptionExtension.IInterceptor interface, and there are three implementations:
It is required that, when you are going to apply an aspect to a registration, you choose an interceptor suitable for that registration, based on what type we are registering.
An aspect itself is an implementation of Microsoft.Practices.Unity.InterceptionExtension.ICallHandler, Unity includes five out of the box such handlers:
Authorization handler (Microsoft.Practices.EnterpriseLibrary.Security.PolicyInjection.AuthorizationCallHandler): for implementing authorization rules;
Exception handling handler (Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.PolicyInjection.ExceptionCallHandler): for applying the rules of the Exception Handling application block;
Logging handler (Microsoft.Practices.EnterpriseLibrary.Logging.PolicyInjection.LogCallHandler): for logging calls before and after a method call using the Logging application block;
Validation handler (Microsoft.Practices.EnterpriseLibrary.Validation.ValidationCallHandler): for validating arguments of a method with the Validation application block;
Performance counter handler (Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.PerformanceCounterCallHandler): for updating a performance counter upon calling a method.
The ICallHandler interface only defines a single method, Invoke, which wraps a method’s arguments and allows having code run before, after or even instead of the target method, and an Order property, for specifying the order by which the aspect should be applied, in case there are many.
A simple call handler, for outputting some string before or after a method call, might be:
Another option is to have interception for all methods of the target registration, which can be achieved by implementing Microsoft.Practices.Unity.InterceptionExtension.IInterceptionBehavior in a concrete class, such as this:
If we want to cancel the default method call, if it is non void, we must return an appropriate value:
Or if we want to return an exception:
There are three ways by which we can apply an aspect to a registration:
By applying an attribute to a method on the declaring or target type;
By code configuration;
By XML configuration.
Interception By Attributes
We need to create an attribute that derives from Microsoft.Practices.Unity.InterceptionExtension.HandlerAttribute and which instantiates our call handler:
And we apply it to any method declaration:
But before this works, we need to tell Unity to use interface interception for our type:
Interception By Code
For intercepting by code, whenever we register something with Unity, we also tell it to use interface interception and to include a behavior instance – it is not possible to specify a call handler for a specific method:
Interception By Configuration
When applying interception by configuration we also cannot target a specific method, but instead specify an interception behavior, which will apply to all method – of course, inside of it we can do our own filtering, by looking at the IMethodInvocation.MethodBase property:
You must Unity to retrieve an instance, which will be properly wrapped in a proxy, and from there all of your configured interceptors will be called:
Next in line: extending Unity.