Click here to Skip to main content
Email Password   helpLost your password?

Introduction

Many times, we need to intercept method calls, and enable some code to run before/after a method call of an external type (.NET object). This article shows how to intercept the methods of an external type, generating method proxies by using injection of IL code.

The dynamic type factory

This factory will generate the dynamic types and return them to the caller. This emulates the external type, and intercepts the specified methods added in the interface. The factory needs the external type and an interface, which establishes the methods that will be intercepted. The sample code here below creates the new type:

public static object Create(object externalTarget, Type interfaceType)
{
    Type proxyType= EmiProxyType(target.GetType(),interfaceType);

    return Activator.CreateInstance(proxyType , 
       new object[]{externalTarget,interfaceType});     
}

After providing the factory with the target object (externalTarget) and the interface (interfaceType which specifies the methods to intercept), we call the method EmiProxyType that builds the method proxy at runtime. Now, the factory can return the enhanced object through reflection.

Defining the interface

As previously said, the interface we pass to the factory specifies which methods we want to intercept; moreover, implemented attributes (AOP) will define the desired behavior.

public interface IBussinesLogicEmployees
{
    [CountingCalls]
     [LoggerToFile]
         EnterpriseDemo.Employees GetEmployees(
             EnterpriseDemo.BussinesLogicEmployees.Delegation delegation);
}

This interface sets the method GetEmployees as interceptable, and defines the attributes CountingCalls and LoggerToFile. If we do not decorate the interface method, the interception code will be empty, so the external method won't execute before/after the additional code.

Defining the attributes

The attributes have tree behaviors inside the method that create the factory:

  1. Before calling to the external method, it must inherit the "BeforeAttribute" class.
  2. After calling to the external method, it must inherit the AfterAttribute class.
  3. If the external method type throws an exception, it must inherit the LogExceptionAttribute class.

By default, implement three attributes:

  1. CountingCalls: this attribute tells the factory to count the number of calls. The action is made before the call to the method of the external type.
  2. LoggerToFile: this attribute tells the factory to generate a log file in which information relative to the access will be stored. The action is made before the call to the external method.
  3. LoggerExceptionToFile: this attribute tells the factory to generate a log file in which information relative to the exception will be stored (in case of the exception being raised by the external method).

Additionally, I have created a custom attribute, ExternalFilter, that will be performed after the execution of the method. It filters the obtained typed dataset according to whether the employee is external or not. The method generated by the factory returns a typed dataset with the external employees, if we decorate the method of the interface with this attribute. In summary, we can extend as many attributes as we want, depending on our needs.

How to intercept an external type method?

To intercept an external type method, we must follow these steps:

  1. Define an interface indicating which are the external type methods to intercept, and what actions the interception code does, depending on the attributes.
  2. Call the factory the following way:
    IBussinesLogicEmployees iBLExternal = 
        (IBussinesLogicEmployees) CodeInjection.Create(
                new BussinesLogicEmployees(), 
                typeof(IBussinesLogicEmployeesExternalFilter)
                );
  3. Execute the intercepted method:
    EnterpriseDemo.Employees dsEd =
        iBLExternal.GetEmployees(BussinesLogicEmployees.Delegation.Madrid);

In our case, looking at the interface method GetEmployees, notice that it's marked with two attributes, CountingCalls and LoggerToFile, so the factory generated method will register the number of calls and will create a log file with information about the method calls.

If, instead, we decorate our interface this way:

public interface IBussinesLogicEmployees {

[LoggerToFile]
[LoggerExceptionToFile]
[ExternalFilter]  
EnterpriseDemo.Employees GetEmployees(
    EnterpriseDemo.BussinesLogicEmployees.Delegation delegation);
}

the factory generated method will create a log file with information about the method call, will create a log file with information about the exception generated by the external type method, will execute the external type method, and finally, will filter the typed dataset returned depending on whether the employees are marked as external or not.

Conclusion

In the .NET platform, Aspect Oriented Programming (AOP) can be achieved mainly on two approaches: injecting the IL with the desired code, or alternatively, inheriting the classes from the .NET CLR Library class ContextBoundObject. Injecting the IL code allows interception of methods on external types. So, we can intercept external methods without needing to have the source code of that external type. We use interfaces to help us decide what methods will be intercepted, and decorate interface methods with attributes to run extra actions.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralMOre on .NET AOP and code injection
Oscar Vera
4:29 24 Mar '08  
I think you should read these two articles on the subject....

"Aspectos e intercepción de métodos en .NET o cómo poner la guinda sin estropear el merengue"
http://www.dotnetmania.com/Articulos/010/index.html

"Reflection.Editor, una biblioteca para programar la edición de ensamblados .NET"
http://www.dotnetmania.com/Articulos/015/index.html

Regards
GeneralCan I add feature to assembly using CodeDOM ?
vgrigor1
2:58 4 Dec '06  
I have same problem :

I need to insert call to begin of the call of some defined and widely used class,
(without interfaces!).

CodeDOM in principle permit to do this feature ?

Once it represent object graph - can I incorporate my call into this graph ?

Or just only can create assembly as a whole?


thanks you
GeneralRe: Can I add feature to assembly using CodeDOM ?
Roberto Loreto
3:18 4 Dec '06  
Hi,

The proxy object only do before/after events. If you requiered to initialize values in the constructor, the external class should have any params in the constructor method.

CodeDOOM is not a good idea because the goal of this sample is generate proxy class at runtime and not in compile-time (with CodeDOM).

Regards,

Roberto
GeneralRe: Can I add feature to assembly using CodeDOM ?
vgrigor1
10:27 4 Dec '06  
Very interesting,

I need miostly - only do before/after events.

How to implement it at runtime, by codeDOM ?
Can you give some link ?

I did not found ANY possibility,
so despite how well or not Idea - first what is need - to have possiblility to evaluate,
so please provide anything how to do it ?


Or - at compile time by else technolog?
How to do it?

Some Idea?
_____________

It is possible to implement Emit to assebly with cust to some interface,
but I have no any interface in class wich I want to tweak...
GeneralRe: Can I add feature to assembly using CodeDOM ?
Roberto Loreto
12:23 4 Dec '06  

CodeDOM generate physical assemblies (compile-time), if you wanna generate IL (.NET intermediate language) at runtime you have used Injection technologies.

Fortunately, .NET provide a System.Reflection.Emit class witch allow build IL code. In this sample, using IL, I generate a proxy type (with Emit) adding (too with Emit) before/after events to the method target witch are defined by interfaces attributes.

You can see the source code and try understand it, even though to built IL code is not a easy task.

I hope help you.

GeneralRe: Can I add feature to assembly using CodeDOM ?
BamYazi
1:48 10 Jan '07  
A nice way of getting to grips with IL is to write a class with the code you want to inject, decompile it with ILDASM and then inspect the generated IL - you'll still need to have a grasp of IL but this will get you 90% of the way there
GeneralCooooooool !!!!
Ricardo Casquete
22:52 5 Jun '06  
Really a cool Article....

Interesting and Practical.... a Good Job...


Regards



Ricardo Casquete
GeneralCastle?
Tutu
21:32 2 Jun '06  
Nice stuff.
Have you considered looking at http://www.castleproject.org[^]?
It provides a very good framework for IOC.

Tutu.

http://www.acorns.com.au


Last Updated 2 Jun 2006 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010