Policy Injection App. Block simple sample

Now with the new version of Enterprise Library 3.0 we can play with Aspect Oriented Programming.

The goal of AOP is to insert some functionality that is not "business related" without altering the existing code or to make it flexible enough so changes are smooth or even better, transparent. The idea is to intercept calls before and after a method is called.

Some of this functionality could be tracing, transactions, performance counters, exception handling, security etc ...

In web scenarios some of this behaviors could be accomplished through httpmodules or http handlers, or SOAP filters. But only, of course, in the entry points of the pages or web services facades. Now it can be implemented in all kind of classes.

The Policy Injection Application Block (PIAB) is great mainly because of its simplicity of use.

There are lots of already built matching rules so we can filter which code we want to intercept to make our "extra functionality" (of course we would seldom want to intercept all calls we want to limit it to an assembly or a namespace) If by some chance this set of rules fall short we could implement a custom one.

Also there are ready build handlers (interceptors), which are great examples and covers the most wanted extra functionality. And of course we can build our own handlers.

 

Here are a couple of samples on how to use it.

The first sample shows how to use the  performance counter. We can achieve it with three steps:

  • Register the performance counter

Just run installutil /category=MyClassCategory Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.dll (from the bin folder of the Enterprise Library )

  • Decorate the method

Set the "PerformanceCounterCallHandler" attribute in the method we want to create the performance counter.

 

[PerformanceCounterCallHandler("MyClassCategory","MyInstanceName2")]

public string MyMethod(string param1)

 

  • Create the wrapped object

IMyClass myClassInstance = (IMyClass)PolicyInjection.Create<MyClass, IMyClass>();

 

Once done that we can call the method and the performance counter will be created and managed automatically.

 

Using perfmon we can see how the performance counter is incremented every time the method is called.

 

 

 The second sample shows how to intercept the exceptions from a method and modify the return value in order to modify the return value of the original method.

We needed to create a handler to manage the exceptions, to make a handler we need to create a class that inherits ICallHandler and decorate it with the ConfigurationElementType attribute.

In the Invoke method we implement the exception handling. If there is some exception in the message we disable it by setting it to null and then we change the return value.

 

public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{

IMethodReturn msg = getNext()(input, getNext);

if (msg.Exception != null)
{
     msg.Exception = null;
     msg.ReturnValue = "Message Exception caught by MyMessageHandler."
}

return msg;

}

 

Then we need to create a policy in the config file of the application to set which code should be intercepted.

With this version of EntLib you can right click the .config file inside Visual Studio 2005 and and select "Edit Enterprise Library Configuration".

Add the Policy Injection Application Block

Add a new policy

if In this sample we created a namespace matching rule and added one namespace name to the collection.

The we added our handler and we are ready to go!

 

 

Don't forget that we still need to wrap the objects being intercepted. We have two options we can create a new object that will be wrapped:

IMyClass myClassInstance = (IMyClass)PolicyInjection.Create<MyClass, IMyClass>();

or wrap an existing object:

MyClass myClassInstance = new MyClass();

IMyClass proxy = PolicyInjection.Wrap<IMyClass>(myClassInstance);

 

The last sample is a tracing handler which the interception works as the previous sample and what changes is the implemented handler. We wanted to create a file that contains the traces with the incoming parameters and its values and the return values. Here's the entire code of the handler:

 

[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class MyTraceHandler : ICallHandler
{

public MyTraceHandler(object o)
{

}

public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{

buildInput(input);

IMethodReturn msg = getNext()(input, getNext);

buildOutput(msg.ReturnValue);

return msg;
}

private void buildOutput(object p)
{

System.IO.File.AppendAllText("C:\\PIABSimpleSampleTrace.txt", "OUTPUT: " + p.ToString() + "\r\n\r\n\r\n\r\n");

}

private void buildInput(IMethodInvocation input)
{

ParameterInfo[] pis = input.MethodBase.GetParameters();

StringBuilder sb = new StringBuilder();
foreach (ParameterInfo pi in pis)
{
sb.Append(pi.Name + ":" + input.Arguments[pi.Name].ToString());
}

System.IO.File.AppendAllText("C:\\PIABSimpleSampleTrace.txt", "METHOD CALLED: " + input.MethodBase.Name + "\r\n");
System.IO.File.AppendAllText("C:\\PIABSimpleSampleTrace.txt", "INPUT: " + sb.ToString() + "\r\n");

}

}

 

 

Enjoy.

PIABSimpleSample.zip