Dynamic Methods
I don't hear it talked about, but the CLR has a very efficient way to generate code at runtime. Probably this is because this code generation stuff is something that is accessible through IL generation only, and that is not for the faint of heart. Nevertheless, there are some very useful uses for this. NHibernate is utilizing this approach to avoid the costs of reflection, for instance.
Let us take a look about a simple scenario, we want to translate any delegate type with two parameters to a call to an instance method on our class:
public class Program { private static void Main(string[] args) { new Program().Execute(); } private void Execute() { //instance that has events that we want to subscribe the adapter to DataGridView dataGridView1 = new DataGridView(); EventInfo ei = dataGridView1.GetType().GetEvent("RowPrePaint"); ParameterInfo[]pia = ei.EventHandlerType.GetMethod("Invoke").GetParameters(); MethodInfo methodInfo = this.GetType().GetMethod("Handler", new Type[]{typeof (object), typeof (object)}); DynamicMethod mtd = new DynamicMethod( "Adapter", typeof(void), new Type[] { typeof (Program), // this pia[0].ParameterType,// sender pia[1].ParameterType // e }, this.GetType(), true); ILGenerator gtr = mtd.GetILGenerator(); gtr.Emit(OpCodes.Ldarg_0); // this gtr.Emit(OpCodes.Ldarg_1); // sender gtr.Emit(OpCodes.Ldarg_2); // e gtr.Emit(OpCodes.Call, methodInfo); gtr.Emit(OpCodes.Ret); // generate a delegate bound to this object instance Delegate dynamicDelegate = mtd.CreateDelegate(typeof(DataGridViewRowPrePaintEventHandler), this); //register the adapter ei.AddEventHandler(dataGridView1, dynamicDelegate); dataGridView1.GetType().GetMethod("OnRowPrePaint", BindingFlags.NonPublic | BindingFlags.Instance) .Invoke(dataGridView1, new object[] { null }); } // method that handles the call public void Handler(object x, object y) { Console.WriteLine("{0}: {1}, {2}", this.GetHashCode(), x, y); } }
Take into account that you are probably going to want to cache the method anyway, but this is a cool, if long winded way of achieving this. Personally, in this scenario I would probably simply write a reflection based wrapper, the complexity doesn't really have justification in such a case, but this is just an example, of course.
Comments
Hi there
I was using the Dynamic Methods for the FileHelpers and are awesome, there are a lot of libraries that simply the process.
This is one of the most hidden and wonderful features of .NET 2.0
http://blog.filehelpers.com/2007/01/improving-filehelpers-performance-now.html
I think that worth a lot the extra effort and if you cache (like you said) the delegate you are done =)
The performance gain is incredible !!
Cheers
You could also use CodeDom to generate this. It would be easier and more readable, but will take longer during the first run.
Omer,
Yes, but dynamic methods can skip visibility calls, so that is a significant advantage.
Regarding reflection based wrappers, check out RunSharp - http://www.codeproject.com/dotnet/runsharp.asp
Boo does some pretty neat things with Dynamic Methods to allow fast duck-typing.
IronPython can compile to dynamic methods, that's a very easy way to create code on the fly.
Omer: Using CodeDom has several disadvantages, worst of them is probably that the generated code is never unloaded or collected by the GC.
I think reading MSIL makes my eyes hurt!
But it is very useful, especially if the code it generates is unit tested, and is isolated.
I have created a dynamic composite factory here:
http://morten.lyhr.dk/PermaLink,guid,aa797b7c-a418-45c0-9510-61dc395d7c2d.aspx
Its not done via DynamicMethod, it creates a whole new class, but MSIL is MSIL. I got it working by creating what i wanted in C#, compiled it to and assembly and opened it in reflector.
Is there a smarter way to do this?
Morten,
that is what I usually do as well :-)
IL generation and developer productivity should never coexist in the same sentence.
Why fight with IL if we can just move over to a dynamic language where you write these kind of runtime extensions in the language itself? If we could do this in Ruby instead, Metaprogramming extensions are well within the reach of mere mortal developers and far simpler mechanically.
I wrote a pretty cool template language that compiled templates into dynamic methods. It's a huge performance win when you know that your code is going to be reusing the same template over and over. Being able to skip visibility checks was especially nice, since it allowed the templates to call helper methods on an internal static class. This allowed me to write as much code as possible in C#, and then "glue" it together using dynamically generated IL.
I was using dynamic methods to dispatch intercepted method calls for a log service (the typical AOP application). They are very, very efficient (the JIT compilation is damn fast, especially compared to reflection). You may check out my blog post: http://tdanecker.blogspot.com/2007/09/interception-with-proxies.html
Ayende
It can be done a little bit smarter.
Look at thsi plug-in for Reflector.
http://www.codeplex.com/reflectoraddins/Wiki/View.aspx?title=ReflectionEmitLanguage&referringTitle=Home
I made a post about it here:
http://morten.lyhr.dk/PermaLink,guid,a844104f-949a-4800-828c-1fde0fc711c1.aspx
Comment preview