Click here to Skip to main content
Click here to Skip to main content

AOP using System.Reflection.Emit - Code Injection IL

By , 2 Jun 2006
 

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

  • Release 1.0, 3 June 2006.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Roberto Loreto
Web Developer
Spain Spain
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5mvpKanasz Robert28 Sep '12 - 7:14 
great article
QuestionRoberto: you Rock!!!!memberRicardoCasquete3 Nov '11 - 13:26 
Top Notch mate !!!!
GeneralMOre on .NET AOP and code injectionmemberOscar Vera24 Mar '08 - 3:29 
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
QuestionCan I add feature to assembly using CodeDOM ?membervgrigor14 Dec '06 - 1:58 
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
AnswerRe: Can I add feature to assembly using CodeDOM ?memberRoberto Loreto4 Dec '06 - 2:18 
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 ?membervgrigor14 Dec '06 - 9:27 
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 ?memberRoberto Loreto4 Dec '06 - 11:23 

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 ?memberBamYazi10 Jan '07 - 0:48 
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 !!!!memberRicardo Casquete5 Jun '06 - 21:52 
Really a cool Article....
 
Interesting and Practical.... a Good Job...
 

Regards
 

 
Ricardo Casquete
QuestionCastle?memberTutu2 Jun '06 - 20:32 
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

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 2 Jun 2006
Article Copyright 2006 by Roberto Loreto
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid