This is the first of a series of articles related to Mono.Cecil tool
“….cecil is a library written by Jb Evain to generate and inspect programs and libraries in the ECMA CIL format […].”…under this statement we start to dive into this amazing library with which we can perform a lot of incredible and interesting things.
According to Jb Evain you can load managed assemblies, browse all its types, modify them on the fly and save the changes of updated assembly. My first impression was to relate it with .NET Reflection and Reflection Emit libraries but the reality is quite different….
….in fact with .NET Reflection API we are able to create new types, integrate them in a new assembly and load this assembly in the same app domain, but we aren´t able to update an existing types, etc.….This apparent subtle difference itself is the basis for a new whole body of possibilities in terms of metaprogramming and code injection.
One of the key for achieving this goal is that Cecil does not need to load the assembly in order to get the features of CLI images; so we are now free for doing updates to existing types and methods inside a given library. In addition Cecil has a rich ecosystem for even extracting CIL bytecodes. Mono.Cecil is open source and it´s part of Mono project exposing an easy to use API for assembly manipulation and code analysis.
With MonoCecil we can overcome some unpleasant issues and limitations of .NET Reflection when dealing, for example, with Late-Binding scenarios, this doesn´t mean .NET Reflection is an unvalid API, in fact is the .NET core solution for providing good practices about metaprogramming patters, but definitely Mono.Cecil is more efficiently when dealing with assembly manipulation; some of the main advantages are the following ones:
- NET Reflection consumes a lot of memory: As we commented earlier you need to load whole assembly even when you need to inspect only a specific types; this is specially noted when the assembly contains a huge amount of types, and from this scenario it´s really difficult to release this amount memory ,even when we use the ready-only load fashion
- Security Limitations: When we inspect the assembly load with Reflection a Code Access Security exception can be thrown
- Usually it has a poor performance: Some of this problem can be related with CAS checks. Obviously we need to avoid direct reflection calls with “invokes” and replace them, for example, with a lamba expression or open delegate built over the same MethodInfo
- At current date it´s not possible to unload one assembly from an AppDomain once it is loaded by .NET Reflection. Microsoft has several reasons for this, the first is that you are running the code inside the same AppDomain, this means that can be potentially call sites and call stack with its addresses that ares supposed to continue working.
Code Instrumentation is a usual topic in modern development IDEs like Visual Studio VS2015 /2017. Application Insights is one example, we can activate it inside our IDE and provide detailed performance metrics about application execution processes.
This type of instrumentation can be easily achieve with Cecil; we can perform any kind of assembly manipulation at IL level and instrument you application code in order to integrate exogenous performance logic (or any kind of logic, in fact) without need code modification or new compilations.
In addition, with Cecil we are also able to generate the corresponding pdb´s files for each instrumented assembly, so that we can debug the instrumented code and even we are able to internally report exception with the exact line of code…..real amazing product !
products implementing cecil
Mono.Cecil can be found as basis of many AOP´s frameworks like SheepAOP, PostCrap and AspectDNG, Code-Reweavers and Assembly Manipulation tool utilities like Fody, CInject, IL-Repack, GPU.NET etc.. Testing tools like MbUnit v3/Galio, MoMa, OpenCover, etc.., Decompilers like ILSpy and Reflector Pro,etc.. Profilers like HNProf, EFProf and .NET Perf, CodeBug-Finding tools like Gendarme, DrivenMetrics, etc.. and even some Obfuscators like DeepSea Obfuscator, CodeWall or XapOptimizer
Here we can take a look to a basic Mono.Cecil class diagram about some of direct types involved in assembly manipulation and code injection
Mono.Cecil is open source and it can be downloaded from GitHub repo: https://github.com/jbevain/cecil
From here, I´ll try to show Cecil power through a series of articles in which I´ll cover some interesting examples and mechanics…
Happy coding !