Wiki
Clone wikiCodeCop / Interceptors
Interceptors
An Interceptor is a class that is used to decorate one method call with additional tasks, e.g. logging, auditing or any other you might want.
To create a new Interceptor, just add a new class to your project and make it implement the ICopIntercept interface.
#!c# public class LoggingInterceptor : ICopIntercept { public void OnBeforeExecute(InterceptionContext context) { // Code in here will run before the method executes } public void OnAfterExecute(InterceptionContext context) { // Code in here will run after the method executes } }
Whenever you want code to be executed before the intercepted method runs you place your code on the OnBeforeExecute method:
#!c# public void OnBeforeExecute(InterceptionContext context) { Console.WriteLine("Before"); }
On the other hand, if you want code to execute after the intercepted method runs, you place your code on the OnAfterExecute method:
#!c# public void OnAfterExecute(InterceptionContext context) { Console.WriteLine("After"); }
Override
You have also the option to run code that surrogates the method logic completely. For that to happen, make your interceptor also implement the ICopOverride interface and place your code on the OnOverride method. By convention an intercepted method can only have one override (with the exception when you use the fluent API where you can have as many as you want). If more than one override is found for the same method, the runtime will throw an exception.
#!c# public class LoggingInterceptor : ICopIntercept, ICopOverride { public void OnBeforeExecute(InterceptionContext context) { // Code in here will run before the method executes } public void OnAfterExecute(InterceptionContext context) { // Code in here will run after the method executes } // This example shows method surrogation. Instead of running the intercepted method original code we will call BarMethod from the same class public object OnOverride(InterceptionContext context) { return context.Sender.BarMethod(); } }
Even when we Override the method it is still possible to let the original method code to run. To do so, call the Execute() extension method.
#!c# public object OnOverride(InterceptionContext context) { public object OnOverride(InterceptionContext context) { object result = null; try { // Still execute the method result = context.InterceptedMethod.Execute(context.Sender, context.Parameters.Select(x => x.Value).ToArray()); } catch (Exception) { } return result; } }
Error Handling
If you want to automatically add exception code and handle errors when interception occurs, you should implement on your interceptor the ICopErrorHandle interface.
Like override there can only be one error handler per intercepted method. If more than one is found, an exception will be thrown.
#!c# // Error Handle without override public class LoggingInterceptor : ICopIntercept, ICopErrorHandle { public void OnBeforeExecute(InterceptionContext context) { // Code in here will run before the method executes } public void OnAfterExecute(InterceptionContext context) { // Code in here will run after the method executes } public void OnError(InterceptionContext context) { Console.WriteLine("An exception occured: {0}", context.Exception.Message"); } }
#!c# // Error Handle with override public class LoggingInterceptor : ICopIntercept, ICopOverride, ICopErrorHandle { public void OnBeforeExecute(InterceptionContext context) { // Code in here will run before the method executes } public void OnAfterExecute(InterceptionContext context) { // Code in here will run after the method executes } public object OnOverride(InterceptionContext context) { return context.Sender.BarMethod(); } public void OnError(InterceptionContext context) { Console.WriteLine("An exception occured: {0}", context.Exception.Message"); } }
InterceptionContext
Whenever you intercept a method you receive as parameter on your interceptor an InterceptionContext object. That object has the following properties :
- Sender - The current class instance that called the intercepted method.
- InterceptedMethod - A MethodBase object that represents the intercepted method.
- Parameters - An array of Parameter objects that represent the parameters passed to the method at the moment of execution.
- GenericArguments - An array that contains all the generic arguments that were used to create a closed generic instance of the intercepted method.
- Timestamp - A DateTime object that contains the date and time when the interception callback took place.
- Exception - If an exception occurs while executing or overriding the method and you have implemented ICopErrorHandle on an interceptor, this property contains the exception itself.
- TransferBag - A generic dictionary to pass custom objects or state between interception phases.
#!c# public void OnBeforeExecute(InterceptionContext context) { Console.WriteLine("Method {0} has been called at {1}", context.InterceptedMethod.Name, context.TimeStamp.ToString()); }
Updated