- Creating a dynamic proxy generator with c# – Part 2 – Interceptor Design
- Creating a dynamic proxy generator with c# – Part 3 – Creating the constructors
- Creating a dynamic proxy generator with c# – Part 4 – Calling the base method
I’ve recently started a project with a few mates to learn the ins and outs of Dependency Injection, AOP and a number of other pretty crucial patterns of development as we’ve all been using these patterns for a while but have relied totally on third part solutions to do the magic.
We thought it would be interesting to really get into the details by rolling our own IoC container and hopefully learn a lot on the way, and you never know, we might even create an excellent framework.
The open source project is called Rapid IoC and is hosted at http://rapidioc.codeplex.com/
One of the most interesting tasks for me is creating the dynamic proxy generator for enabling Aspect Orientated Programming (AOP).
In this series of articles, I’m going to track each step I take for creating the dynamic proxy generator and I’ll try my best to explain what everything means - mainly as I’ll be using Reflection.Emit to emit a fair amount of intermediate language code (IL) to create the proxy types at runtime which can be a little taxing to read.
It’s worth noting that building the proxy is without a doubt going to be slightly painful so I imagine there will be plenty of areas I’ll need to change along the way.
Anyway lets get started…
Part 1 - Creating the Assembly builder, Module builder and caching mechanism
Part 1 is going to be a really nice simple start, I’m just going to start by creating the assembly, module and type caches.
The reason we need to create caches for the assembly, module and types is simply to save the overhead of recreating proxy types that have already been generated, this will be one of the important steps to ensure that the framework is fast… kind of important as we’re calling the IoC container ‘Rapid’ – will be a little bit embarrassing if we manage to create the slowest framework.
The Assembly builder
The assembly builder is what is used to create an assembly at runtime, we’re going to have two overloads, one will be for the actual use of the proxy generator, the other will be mainly for testing purposes as it will also save the assembly so we can use Reflector to examine the code that has been created.
Here’s the code:
So hopefully the above class is fairly explanatory, an AssemblyName is created using the passed in string for the actual name of the assembly.
An AssemblyBuilder is then constructed with the current AppDomain and depending on the overload used, it is either just run in the current context or it is set up ready for saving.
It is then added to the cache.
The cache is simply a static property that will store the AssemblyBuilder (I know it’s a little weird that I’ve made it public, this is for testing purposes, I know that’s a bad excuse but hey…)
There are two methods for using the cache – Add and Get, these just provide thread safe access to the cache.
The Module Builder
The module builder is required as the create proxy classes will need to live inside a module within the assembly.
Here’s the code:
As you can see, the module builder is created on the assembly that lives in the DynamicAssemblyCache, the module is given the assembly name and also a string representing the filename if the assembly is to be saved.
It is then added to the DynamicModuleCache.
The DynamicModuleCache is very similar to the assembly cache, it is simply a statically stored module with thread safe Add and Get methods.
To end off this post, I’m going to create the cache for storing the generated proxy classes.
I’ve spent a fair amount of time thinking about the type of collection I should use to store the types and have finally decided that for the time being I’m going to use a generic dictionary.
This may change when I can actually performance test the proxy generator but the time being I think it makes good sense in theory, mainly as it pretty much maintains it’s performance with varying numbers of items – almost constant (0)1.
Plus I won’t ever need to loop through the items which is not the dictionaries strong point.
Here’s the code as it currently stands:
As you can see, there are two public methods, one for adding to the cache and one for getting from the cache. Hopefully they should be clear enough, the Get is a TryGet as I do not want the dictionary to throw an exception if a proxy doesn’t exist within the cache.
Other than that I’ve decided to create a key using the SHA1CryptoServiceProvider, this may change but my initial though is the SHA1 algorithm is pretty fast to put together using the provider and it is also very unlikely to have any hashing collisions. (there are some maths behind how unlikely this is – here’s the wiki if you’re interested http://en.wikipedia.org/wiki/SHA_hash_functions)
Anyway, that’s the end of part 1 – although I haven’t started any of the fun stuff (by fun I mean hairpulling, teeth grating Relfection.Emit style fun), I’ve got the basis of the DynamicProxy in place so all we have to worry about now is creating the types, interceptor classes, method invocation information classes and finally a really nice fluent interface that will abstract all of the hard-core craziness away and leave us with a lightning fast, easy to use AOP framework.
Hope you find the series interesting.
All of the source code can be viewed and/or downloaded at our codeplex site - http://rapidioc.codeplex.com/