With the introduction of Unity v1.2 it is now possible to do aspect oriented programming (AOP) using Unity in a way that is similar to Policy Injection. You can read all about it in my former post How-to AOP: Validation with Policy Injection, where I showed how-to AOP using Validation with the Policy Injection Application Block (PIAB).
The example of today is a rework of the previous Policy Injection example, so most code remains unchanged. Most important exercise is that the invoking code in the method Save of the facade CustomerManager is changed so – surprise, surprise – Unity does the AOP work instead of Policy Injection.
Unfortunately, out-of-the-box Unity does not have something like an ArgumentValidationException.
So, some extra code has to be written, mostly to make Unity do its AOP thing work. To stay in line with the PIAB example, some behavior of the Policy Injection ValidationCallHandler is mimiced: when validation fails, an exception is thrown.
Of course, you can reuse the ArgumentValidationException of PIAB, but then you still need PIAB. For this example, I am an Unity purist and create something myself that looks like an ArgumentValidationException, smells like an ArgumentValidationException, in fact is called an…
… EntityValidationException.
Yeah right, I gave it a different name for educational purposes so you wouldn’t think: Wow, Unity also has this powerful way of handling validation. What a great piece of work this Unity is!
Well, maybe Policy Injection will fully integrated in the next version of Unity. Maybe not.
First, you have to change the code in the method Save of CustomerManager to use Unity:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public bool Save(Customer customer) { bool IsValid = false; IUnityContainer container = new UnityContainer(); container.AddNewExtension(); container.RegisterType().Configure().SetInterceptorFor(new InterfaceInterceptor()); IRepository action = container.Resolve(); try { action.Save(customer); } catch (EntityValidationException ex) { ValidationResults results = ex.ValidationResults; // ... } return IsValid; } |
Essentially, this is the most important part of the exercise. As you can see, Unity uses an interception mechanism for the AOP behavior. As in the Policy Injection example, an interface is needed for registering the type. Unity has no built-in ValidationCallHandler like Policy Injection, so you have to create one yourself. This is not very difficult, see below:
|
1 2 3 4 5 |
public interface IRepository { [EntityValidation] void Save(Customer customer); } |
EntityValidation is a concrete HandlerAttribute:
|
1 2 3 4 5 6 7 |
public class EntityValidationAttribute : HandlerAttribute { public override ICallHandler CreateHandler(IUnityContainer container) { return new EntityValidationHandler(); } } |
A HandlerAttribute needs to return a concrete class which implements ICallHandler:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class EntityValidationHandler : ICallHandler { public int Order { get; set; } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { Customer customer = input.Arguments[0] as Customer; ValidationResults results = Validation.Validate(customer); if (results.Count == 0) { return getNext()(input, getNext); } else { throw new EntityValidationException(results); } } } |
Lastly, you need an exception to mimic the ArgumentValidationException:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
[Serializable] public class EntityValidationException : Exception, ISerializable { readonly private ValidationResults validationResults; public EntityValidationException(ValidationResults validationResults) { this.validationResults = validationResults; } protected EntityValidationException(SerializationInfo info, StreamingContext context) : base(info, context) { this.validationResults = (ValidationResults)info.GetValue("EntityValidationException.validationResults", typeof(ValidationResults)); } public ValidationResults ValidationResults { get { return validationResults; } } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("EntityValidationException.validationResults", validationResults); } } |
That’s most of it. Nice, huh? To be honest with you: I slightly prefer Policy Injection over Unity Interception. Why? It feels like the subtle difference Policy Injection is AOP and Unity supports AOP. It’s just a feeling.
Comments