<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Haibo Luo's weblog : DynamicMethod</title><link>http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx</link><description>Tags: DynamicMethod</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Late-bound Array SetValue</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/11/26/1157785.aspx</link><pubDate>Mon, 27 Nov 2006 08:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1157785</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/1157785.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=1157785</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=1157785</wfw:comment><description>&lt;p&gt;The type "&lt;a href="http://msdn2.microsoft.com/en-us/library/system.array.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.array.aspx"&gt;System.Array&lt;/a&gt;" provides us a set of API for the late-bound array operations, including array creation (&lt;a href="http://msdn2.microsoft.com/en-us/library/system.array.createinstance.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.array.createinstance.aspx"&gt;Array.CreateInstance&lt;/a&gt;), read/write access to array element (&lt;a href="http://msdn2.microsoft.com/en-us/library/system.array.setvalue.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.array.setvalue.aspx"&gt;Array.SetValue&lt;/a&gt;/&lt;a href="http://msdn2.microsoft.com/en-us/library/system.array.getvalue.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.array.getvalue.aspx"&gt;Array.GetValue&lt;/a&gt;). They are convenient to use. Let me start with some code to create an one-dimensional integer array, and set the first 2 elements using early-bind assignment and Array.SetValue, respectively. To simplify my code, this post will only touch the late-bound set value on array (the similar discussion can be applied to get value).&lt;/p&gt;
&lt;div class="csharp"&gt;&lt;span class="cscomment"&gt;// creation: new int[5]&lt;/span&gt;&lt;br&gt;&lt;span class="cstype"&gt;Array&lt;/span&gt; x = &lt;span class="cstype"&gt;Array&lt;/span&gt;.CreateInstance(&lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;int&lt;/span&gt;), 5);&lt;br&gt;&lt;br&gt;&lt;span class="cscomment"&gt;// 0. early-bind set: explicit cast to int[]&lt;/span&gt;&lt;br&gt;&lt;span class="cskeyword"&gt;int&lt;/span&gt;[] y = (&lt;span class="cskeyword"&gt;int&lt;/span&gt;[])x;&lt;br&gt;y[0] = 100;&lt;br&gt;&lt;br&gt;&lt;span class="cscomment"&gt;// 1. late-bound set via Array.SetValue&lt;/span&gt;&lt;br&gt;x.SetValue(200, 1);&lt;br&gt;&lt;/div&gt;
&lt;p&gt;From the signature of &lt;a href="http://msdn2.microsoft.com/en-us/library/kk3bwkb0.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/kk3bwkb0.aspx"&gt;Array.SetValue(object, int)&lt;/a&gt;, we know that the integer "200" has to be boxed first before passing into this API, which is a performance hit (among others). However, we can take a look at what kind of IL sequence C# compiler generates for the early-bound assignment, and build an equivalent dynamic method to avoid the boxing: C# compiler emits Stelem.I4 to store the 32-bit integer value.&lt;/p&gt;
&lt;div class="csharp"&gt;&lt;span class="cscomment"&gt;// 2. late-bound set via DynamicMethod/Delegate/OpCodes.Stelem&lt;/span&gt;&lt;br&gt;&lt;span class="cstype"&gt;DynamicMethod&lt;/span&gt; dm = &lt;span class="cskeyword"&gt;new&lt;/span&gt; &lt;span class="cstype"&gt;DynamicMethod&lt;/span&gt;(&lt;span class="csstring"&gt;"SetValueByStelem&lt;/span&gt;", &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;void&lt;/span&gt;),&lt;br&gt;&lt;span class="cskeyword"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new&lt;/span&gt; Type[] { &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;Array&lt;/span&gt;), &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;int&lt;/span&gt;), &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;int&lt;/span&gt;) }, &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;Test&lt;/span&gt;));&lt;br&gt;ILGenerator ilgen = dm.GetILGenerator();&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Ldarg_0);&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Castclass, x.GetType());&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Ldarg_1); &lt;span class="cscomment"&gt;// index&lt;/span&gt;&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Ldarg_2); &lt;span class="cscomment"&gt;// value&lt;/span&gt;&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Stelem_I4);&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Ret);&lt;br&gt;&lt;span class="cstype"&gt;MySetValue&lt;/span&gt; sv = (&lt;span class="cstype"&gt;MySetValue&lt;/span&gt;)dm.CreateDelegate(&lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;MySetValue&lt;/span&gt;));&lt;br&gt;&lt;br&gt;sv(x, 2, 300);&lt;br&gt;&lt;/div&gt;
&lt;div class="csharp"&gt;&lt;span class="cskeyword"&gt;delegate&lt;/span&gt; &lt;span class="cskeyword"&gt;void&lt;/span&gt; &lt;span class="cstype"&gt;MySetValue&lt;/span&gt;(&lt;span class="cstype"&gt;Array&lt;/span&gt; array, &lt;span class="cskeyword"&gt;int&lt;/span&gt; index, &lt;span class="cskeyword"&gt;int&lt;/span&gt; value);&lt;br&gt;&lt;/div&gt;
&lt;p&gt;The runtime (so is System.Array) supports non-zero lowerbound array (C# does not). The code snippet below creates a length-of-5 integer array with -3 as its' lower-bound, and then tries to set value for some elements.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can no longer cast such array to int[].&lt;/li&gt;
&lt;li&gt;Array.SetValue works. Note we need use the lowerbound value to access the first element. &lt;/li&gt;
&lt;li&gt;The instructions "stelem/stelem.&amp;lt;type&amp;gt;" are for one dimensional array with zero-based index only. So the dynamic method approach with stelem instruction won't work. &lt;/li&gt;
&lt;li&gt;For each concrete array type, runtime adds three special methods: &lt;b&gt;Get/Set/Address&lt;/b&gt;. With reflection we can hold those MethodInfo, so you can call MethodInfo.Invoke or create another dynamic method wrapper around it. This works for zero-based array too. &lt;/li&gt;&lt;/ul&gt;
&lt;div class="csharp"&gt;&lt;span class="cscomment"&gt;// creation: new int[-3..1]&lt;/span&gt;&lt;br&gt;&lt;span class="cstype"&gt;Array&lt;/span&gt; x = &lt;span class="cstype"&gt;Array&lt;/span&gt;.CreateInstance(&lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;int&lt;/span&gt;), &lt;span class="cskeyword"&gt;new&lt;/span&gt; &lt;span class="cskeyword"&gt;int&lt;/span&gt;[] { 5 }, &lt;span class="cskeyword"&gt;new&lt;/span&gt; &lt;span class="cskeyword"&gt;int&lt;/span&gt;[] { -3 });&lt;br&gt;&lt;br&gt;&lt;span class="cscomment"&gt;// 1. late-bound set via Array.SetValue&lt;/span&gt;&lt;br&gt;x.SetValue(200, 1 - 3);&lt;br&gt;&lt;br&gt;&lt;span class="cscomment"&gt;// 3. late-bound set via MethodInfo.Invoke of "Set"&lt;/span&gt;&lt;br&gt;&lt;span class="cstype"&gt;MethodInfo&lt;/span&gt; mi = x.GetType().GetMethod(&lt;span class="csstring"&gt;"Set&lt;/span&gt;");&lt;br&gt;mi.Invoke(x, &lt;span class="cskeyword"&gt;new&lt;/span&gt; &lt;span class="cskeyword"&gt;object&lt;/span&gt;[] { 3 - 3, 400 });&lt;br&gt;&lt;br&gt;&lt;span class="cscomment"&gt;// 4. late-bound set via DynamicMethod/Delegate/"Set"&lt;/span&gt;&lt;br&gt;&lt;span class="cstype"&gt;DynamicMethod&lt;/span&gt; dm = &lt;span class="cskeyword"&gt;new&lt;/span&gt; &lt;span class="cstype"&gt;DynamicMethod&lt;/span&gt;(&lt;span class="csstring"&gt;"SetValueBySet&lt;/span&gt;", &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;void&lt;/span&gt;),&lt;br&gt;&lt;span class="cskeyword"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new&lt;/span&gt; Type[] { &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;Array&lt;/span&gt;), &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;int&lt;/span&gt;), &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;int&lt;/span&gt;) }, &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;Test&lt;/span&gt;));&lt;br&gt;&lt;br&gt;ILGenerator ilgen = dm.GetILGenerator();&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Ldarg_0);&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Castclass, x.GetType());&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Ldarg_1);&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Ldarg_2);&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Call, mi);&lt;br&gt;ilgen.Emit(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;.Ret);&lt;br&gt;&lt;br&gt;&lt;span class="cstype"&gt;MySetValue&lt;/span&gt; sv = (&lt;span class="cstype"&gt;MySetValue&lt;/span&gt;)dm.CreateDelegate(&lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;MySetValue&lt;/span&gt;));&lt;br&gt;sv(x, 4 - 3, 500);&lt;br&gt;&lt;/div&gt;
&lt;p&gt;Using Vance's &lt;a href="http://blogs.msdn.com/vancem/archive/2006/09/21/765648.aspx" mce_href="http://blogs.msdn.com/vancem/archive/2006/09/21/765648.aspx"&gt;CodeTimers&lt;/a&gt; class, I measured &lt;a href="http://blogs.msdn.com/haibo_luo/pages/1157743.aspx" mce_href="http://blogs.msdn.com/haibo_luo/pages/1157743.aspx"&gt;these 5 approaches' performance&lt;/a&gt; on my Vista machine. My scenario is to set value on 1-dimensional zero-based integer array, the action loop contains 10 lines of set-value code (those dynamic method and delegate creation are prepared ahead). The fastest late-bound set approach is DynamicMethod with Stelem, about 90-times slower than the early-bound assignment; but it is 3-times faster than Array.SetValue. Here is the raw output: &lt;/p&gt;
&lt;div class="csharp"&gt;Data units of msec resolution = 0.279365 usec&lt;br&gt;Early-bound assignment &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; : count: 1000000 &amp;nbsp;&amp;nbsp; 4.525 +- 1% msec&lt;br&gt;Late-bound set via Array.SetValue &amp;nbsp; &amp;nbsp; &amp;nbsp; : count: 1000000 1138.182 +- 2% msec&lt;br&gt;Late-bound set via DynamicMethod/Stelem : count: 1000000 &amp;nbsp;397.005 +- 0% msec&lt;br&gt;Late-bound set via Set MethodInfo.Invoke: count: 1000000 36352.360 +- 0% msec&lt;br&gt;Late-bound set via DynamicMethod/Set &amp;nbsp;&amp;nbsp; : count: 1000000&amp;nbsp; 453.956 +- 7% msec&lt;br&gt;&lt;/div&gt;
&lt;p&gt;What about multi-dimensional array? Array.SetValue still works; for better performance, we might want use the special "Set" method. By the way, the following ildasm output shows what C# compiler generates for "array[0, 1] = 1000;", which uses "Set". Note "int32[0..., 0...]" is TypeSpec(0x1B).&lt;/p&gt;
&lt;div class="ilcode"&gt;IL_0009: ldloc.0&lt;br&gt;IL_000a: ldc.i4.0&lt;br&gt;IL_000b: ldc.i4.1&lt;br&gt;IL_000c: ldc.i4 0x3e8&lt;br&gt;IL_0011: call instance void int32[0...,0...]/* 1B000003 */::Set(int32, int32, int32) /* 0A000020 */&lt;br&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1157785" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/1157785.ashx" length="3690" type="text/plain" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>Take Two: IL Visualizer</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx</link><pubDate>Fri, 17 Nov 2006 03:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1090671</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/1090671.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=1090671</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=1090671</wfw:comment><description>&lt;P&gt;I was glad to hear many positive feedbacks about the &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2005/10/25/DebuggerVisualizer-for-DynamicMethod-_2800_Show-me-the-IL_2900_.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2005/10/25/DebuggerVisualizer-for-DynamicMethod-_2800_Show-me-the-IL_2900_.aspx"&gt;DebuggerVisualizer for DynamicMethod&lt;/A&gt;; on the sad side, it shows our lack of good LCG debugging support (on which, Mike Stall is &lt;A href="http://blogs.msdn.com/jmstall/archive/2006/11/14/lcg-feedback.aspx" mce_href="http://blogs.msdn.com/jmstall/archive/2006/11/14/lcg-feedback.aspx"&gt;seeking your opinion&lt;/A&gt;).&lt;/P&gt;
&lt;P&gt;Recently along with the &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2006/11/06/system-reflection-based-ilreader.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/11/06/system-reflection-based-ilreader.aspx"&gt;ILReader&lt;/A&gt; update, I made a few changes on the visualizer:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Add support to show IL of RuntimeMethodInfo and RuntimeConstructorInfo (besides DynamicMethod). Actually &lt;A href="http://weblogs.asp.net/rosherove/default.aspx" mce_href="http://weblogs.asp.net/rosherove/default.aspx"&gt;Roy&lt;/A&gt; already had a &lt;A href="http://weblogs.asp.net/rosherove/archive/2006/04/25/MethodsVisualizer.aspx" mce_href="http://weblogs.asp.net/rosherove/archive/2006/04/25/MethodsVisualizer.aspx"&gt;version&lt;/A&gt; providing such functionality. Last year, I wanted to enable viewing IL on &lt;A href="http://static.flickr.com/115/290216961_cf7c1184fd_o.jpg" mce_href="http://static.flickr.com/115/290216961_cf7c1184fd_o.jpg"&gt;all MethodBase-derived types&lt;/A&gt;. Well, my daily duty and interests changed; I am afraid I won't ever meet that goal.&lt;/LI&gt;
&lt;LI&gt;Add support to show IL of Delegate.MethodInfo, where the delegate might be created from DynamicMethod.&lt;/LI&gt;
&lt;LI&gt;Simplify IL Visualizer UI. When the DynamicMethod IL code is incomplete, those branch instructions' label shown inside the visualizer could be incorrect. However it is easy to identify this fixup failure: they always branch to the next instruction. I removed the label-fix-succeed-failed information as well as the font ComboBox at the bottom of the dialog. Now changing the font is done by the RichTextBox's context menu.&lt;/LI&gt;
&lt;LI&gt;Add another way to view IL: "Send to IL Monitor". DebuggerVisualizer dialog is a modal dialog, which means we have to dismiss it first to continue anything with Visual Studio. I found this is inconvenient when trying to track the whole code-gen process. You can now choose "Send to IL Monitor". Before clicking it, a separate application "ilmonitor.exe" need to be started first. Those IL information is sent to this application with TCP socket (and the listening port number is hard-coded as 22017). For one dynamic method, if we click the magnifying glass "Send to IL Monitor" button a couple of times at different code-gen stages, the same window will show the growing IL with different background colors. As you see from the pictures below, it can also track many dynamic methods' IL.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;You may download the attachment and try to build the solutions in your VS. The images below were captured in my Vista box.&lt;/P&gt;
&lt;P&gt;&lt;IMG alt=rtdm src="http://static.flickr.com/102/299076213_ba418437a5_o.jpg" width=571 height=205 mce_src="http://static.flickr.com/102/299076213_ba418437a5_o.jpg"&gt;&lt;BR&gt;&lt;IMG alt=visualizer src="http://static.flickr.com/103/299076214_7b29d24ec6_o.jpg" width=518 height=300 mce_src="http://static.flickr.com/103/299076214_7b29d24ec6_o.jpg"&gt;&lt;BR&gt;&lt;IMG alt=ilmonitor src="http://static.flickr.com/118/299076211_15407e1d41_o.jpg" width=732 height=591 mce_src="http://static.flickr.com/118/299076211_15407e1d41_o.jpg"&gt; &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Disclaimer: THE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES INTENDED OR IMPLIED. USE AT YOUR OWN RISK.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;update&lt;/STRONG&gt; (3/7/2008): VS2008 solution can be found at &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2008/03/07/8107924.aspx"&gt;http://blogs.msdn.com/haibo_luo/archive/2008/03/07/8107924.aspx&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1090671" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/1090671.ashx" length="48737" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>Turn MethodInfo to DynamicMethod</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/11/07/turn-methodinfo-to-dynamicmethod.aspx</link><pubDate>Wed, 08 Nov 2006 01:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1023508</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/1023508.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=1023508</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=1023508</wfw:comment><description>&lt;P&gt;I do not know why anyone ever need this :) but few readers did ask me similar questions before. Solving this problem also demonstrates one more &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2006/11/06/system-reflection-based-ilreader.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/11/06/system-reflection-based-ilreader.aspx"&gt;ILReader&lt;/A&gt; usage.&lt;/P&gt;
&lt;P&gt;To build a DynamicMethod, we can choose either &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.ilgenerator.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.ilgenerator.aspx"&gt;DynamicILGenerator&lt;/A&gt; or &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.aspx"&gt;DynamicILInfo&lt;/A&gt;. My first impression of using DynamicILGenerator to emit code is slow: you need make calls to emit ILs instruction by instruction. Actually this approach is more difficult, a topic for future post. I already wrote a &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx"&gt;post&lt;/A&gt; about DynamicILInfo. I do not know the motivation behind the DynamicILInfo class (at that time I was not in the CLR team), but I heard this was a feature request from SQL.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To turn a MethodInfo to DynamicMethod, we can not simply call &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.setcode.aspx"&gt;SetCode&lt;/A&gt; with the byte array returned by the static method body's &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.getilasbytearray.aspx"&gt;GetILAsByteArray&lt;/A&gt;. Those tokens (if any) are metadata tokens, meaningful only in the scope of the module where that static method lives. The &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.gettokenfor.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.gettokenfor.aspx"&gt;DynamicILInfo.GetTokenFor&lt;/A&gt; overloads are designed to build the relationship between an integer number (the new "token") and the runtime member (type, method, field, string, or signature...) in the scope of the dynamic method.&amp;nbsp;We can first make a copy of the static method's IL byte array, and overwrite the old metadata token with the new token from GetTokenFor for each applicable IL instruction. So here comes ILInfoGetTokenVisitor. As you see, we override 6 visit methods in ILInfoGetTokenVisitor, doing the token replacements; the top-level code to prepare new code array looks simple.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;class&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILInfoGetTokenVisitor&lt;/SPAN&gt; : &lt;SPAN class=cstype&gt;ILInstructionVisitor&lt;/SPAN&gt; {&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; private&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;DynamicILInfo&lt;/SPAN&gt; ilInfo;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; private byte&lt;/SPAN&gt;[] code;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILInfoGetTokenVisitor&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DynamicILInfo&lt;/SPAN&gt; ilinfo, &lt;SPAN class=cskeyword&gt;byte&lt;/SPAN&gt;[] code) {&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; &amp;nbsp; this&lt;/SPAN&gt;.ilInfo = ilinfo;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; &amp;nbsp; this&lt;/SPAN&gt;.code = code;&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineMethodInstruction(&lt;SPAN class=cstype&gt;InlineMethodInstruction&lt;/SPAN&gt; inlineMethodInstruction) {&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ilInfo.GetTokenFor(inlineMethodInstruction.Method.MethodHandle,&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; inlineMethodInstruction.Method.DeclaringType.TypeHandle),&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; inlineMethodInstruction.Offset + inlineMethodInstruction.OpCode.Size);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineFieldInstruction(&lt;SPAN class=cstype&gt;InlineFieldInstruction&lt;/SPAN&gt; inlineFieldInstruction) { ... }&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineSigInstruction(&lt;SPAN class=cstype&gt;InlineSigInstruction&lt;/SPAN&gt; inlineSigInstruction) { ... } &lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineStringInstruction(&lt;SPAN class=cstype&gt;InlineStringInstruction&lt;/SPAN&gt; inlineStringInstruction) { ... }&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineTokInstruction(&lt;SPAN class=cstype&gt;InlineTokInstruction&lt;/SPAN&gt; inlineTokInstruction) { ... }&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineTypeInstruction(&lt;SPAN class=cstype&gt;InlineTypeInstruction&lt;/SPAN&gt; inlineTypeInstruction) { ... }&lt;BR&gt;&amp;nbsp; ...&lt;BR&gt;} &lt;BR&gt;&lt;/DIV&gt;&lt;BR&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;private static void&lt;/SPAN&gt; SetCode(&lt;SPAN class=cstype&gt;MethodInfo&lt;/SPAN&gt; method, &lt;SPAN class=cstype&gt;MethodBody&lt;/SPAN&gt; body, &lt;SPAN class=cstype&gt;DynamicILInfo&lt;/SPAN&gt; ilInfo) {&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; byte&lt;/SPAN&gt;[] code = body.GetILAsByteArray(); &lt;BR&gt;&lt;SPAN class=cstype&gt;&amp;nbsp; ILReader&lt;/SPAN&gt; reader = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILReader&lt;/SPAN&gt;(method);&lt;BR&gt;&lt;SPAN class=cstype&gt;&amp;nbsp; ILInfoGetTokenVisitor&lt;/SPAN&gt; visitor = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILInfoGetTokenVisitor&lt;/SPAN&gt;(ilInfo, code);&lt;BR&gt;&amp;nbsp; reader.Accept(visitor); &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ilInfo.SetCode(code, body.MaxStackSize);&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;JAY was asking &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx#527435" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx#527435"&gt;how to set exceptions&lt;/A&gt;. Reflection does not provide API to return the exception blob directly, instead the exception information is exposed through the &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.exceptionhandlingclauses.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.exceptionhandlingclauses.aspx"&gt;MethodBody.ExceptionHandlingClauses&lt;/A&gt; property. With this ExceptionHandlingClause list, we can follow the format described by Ecma 335 (Part 2, 25.4.5 and 25.4.6) and build the exception blob from scratch. To avoid worrying about the restriction of the small version of exception handling clauses, the exception array generated below is with the fat form layout. See some comments inside the code.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;private static void&lt;/SPAN&gt; SetExceptions(&lt;SPAN class=cstype&gt;MethodBody&lt;/SPAN&gt; body, &lt;SPAN class=cstype&gt;DynamicILInfo&lt;/SPAN&gt; ilInfo) {&lt;BR&gt;&lt;SPAN class=cstype&gt;&amp;nbsp; IList&lt;/SPAN&gt;&amp;lt;&lt;SPAN class=cstype&gt;ExceptionHandlingClause&lt;/SPAN&gt;&amp;gt; ehcs = body.ExceptionHandlingClauses;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; int&lt;/SPAN&gt; ehCount = ehcs.Count;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; if&lt;/SPAN&gt; (ehCount == 0) &lt;SPAN class=cskeyword&gt;return&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cscomment&gt;&amp;nbsp; // Let us do FAT exception header&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; int&lt;/SPAN&gt; size = 4 + 24 * ehCount;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; byte&lt;/SPAN&gt;[] exceptions = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;byte&lt;/SPAN&gt;[size];&lt;BR&gt;&lt;BR&gt;&amp;nbsp; exceptions[0] = 0x01 | 0x40; &lt;SPAN class=cscomment&gt;//Offset: 0, Kind: CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp; OverwriteInt32(size, 1, exceptions); &lt;SPAN class=cscomment&gt;// Offset: 1, DataSize: n * 24 + 4&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; int&lt;/SPAN&gt; pos = 4;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; foreach&lt;/SPAN&gt; (&lt;SPAN class=cstype&gt;ExceptionHandlingClause&lt;/SPAN&gt; ehc &lt;SPAN class=cskeyword&gt;in&lt;/SPAN&gt; ehcs) {&lt;BR&gt;&lt;SPAN class=cscomment&gt;&amp;nbsp; &amp;nbsp; // Flags, TryOffset, TryLength, HandlerOffset, HandlerLength: all size 4&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32((&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;)ehc.Flags, pos, exceptions); pos += 4;&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.TryOffset, pos, exceptions); pos += 4;&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.TryLength, pos, exceptions); pos += 4;&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.HandlerOffset, pos, exceptions); pos += 4;&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.HandlerLength, pos, exceptions); pos += 4; &lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cscomment&gt;&amp;nbsp; &amp;nbsp; // ClassToken or FilterOffset&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;switch&lt;/SPAN&gt; (ehc.Flags) {&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;case&lt;/SPAN&gt; ExceptionHandlingClauseOptions.Clause:&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt; token = ilInfo.GetTokenFor(ehc.CatchType.TypeHandle);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; OverwriteInt32(token, pos, exceptions);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;case&lt;/SPAN&gt; ExceptionHandlingClauseOptions.Filter:&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.FilterOffset, pos, exceptions);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;case&lt;/SPAN&gt; ExceptionHandlingClauseOptions.Fault:&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;throw new&lt;/SPAN&gt; NotSupportedException(&lt;SPAN class=csstring&gt;"dynamic method does not support fault clause"&lt;/SPAN&gt;);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;case&lt;/SPAN&gt; ExceptionHandlingClauseOptions.Finally:&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp; &amp;nbsp; }&lt;BR&gt;&amp;nbsp; &amp;nbsp; pos += 4;&lt;BR&gt;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ilInfo.SetExceptions(exceptions);&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;If you are interested in the details, you may download the attachment and read the whole source code closely.&lt;/P&gt;
&lt;P&gt;A related question is how to build a dynamic method from other sources. DynamicMethod is not &lt;A href="http://msdn2.microsoft.com/en-us/library/system.serializableattribute.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.serializableattribute.aspx"&gt;Serializable&lt;/A&gt;, .NET framework built-in serializing/deserializing support will not work. One approach I can think of is to preserve the code array, the members/strings/... (in order to call GetTokenFor to get new tokens) used and their matching offsets (with one scan of&amp;nbsp;the ILs). MethodInfo, FieldInfo, Type are marked "Serializable", but not sure whether this is the right way to save/restore those members. If the method handles exception, we can save the pre-calculated exception blob, and remember where we need replace token for what exception type.&lt;/P&gt;
&lt;P&gt;Finally, let us play with the turn-static-method-to-dynamic-method call, and show off some IronPython code. The first 3 lines bring in the DynamicMethodHelper class. Then we use Reflection to get DateTime.get_Now's MethodInfo (sGetNow), and convert it to DynamicMethod (dGetNow) with "DynamicMethodHelper.ConvertFrom". The last part of the code is interesting: it converts the method "DynamicMethodHelper.ConvertFrom" to DynamicMethod (dConvert), and use that dynamic method (dConvert) to convert sGetNow to another dynamic method (dGetNow2). Just fyi: DateTime.get_Now has 5 instructions, DynamicMethodHelper.ConvertFrom has ~80 instructions and exception handlings clauses.&lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import clr, System&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;clr.AddReference('ClrTest.Reflection.DynamicMethodHelper.dll')&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;from ClrTest.Reflection import *&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;clr.GetClrType(System.DateTime).GetMethod("get_Now")&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.RuntimeMethodInfo object at 0x000000000000002B [System.DateTime get_Now()]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;sGetNow = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;DynamicMethodHelper.ConvertFrom(sGetNow)&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.Emit.DynamicMethod object at 0x000000000000002C [System.DateTime get_Now()]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dGetNow = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dGetNow.Invoke(None, None)&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.DateTime object at 0x000000000000002D [11/7/2006 11:40:49 AM]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;clr.GetClrType(DynamicMethodHelper).GetMethod("ConvertFrom")&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.RuntimeMethodInfo object at 0x000000000000002E [System.Reflection.Emit.DynamicMethod ConvertFrom(System.Reflection.MethodInfo)]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;sConvert = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;DynamicMethodHelper.ConvertFrom(sConvert)&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.Emit.DynamicMethod object at 0x000000000000002F [System.Reflection.Emit.DynamicMethod ConvertFrom(System.Reflection.MethodInfo)]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dConvert = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dConvert.Invoke(None, System.Array[object]([sGetNow]))&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.Emit.DynamicMethod object at 0x0000000000000030 [System.DateTime get_Now()]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dGetNow2 = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dGetNow2.Invoke(None, None)&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.DateTime object at 0x0000000000000031 [11/7/2006 11:40:59 AM]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;BR&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1023508" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/1023508.ashx" length="8862" type="text/plain" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>System.Reflection-based ILReader</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/11/06/system-reflection-based-ilreader.aspx</link><pubDate>Mon, 06 Nov 2006 23:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1003788</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/1003788.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=1003788</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=1003788</wfw:comment><description>&lt;P&gt;Compared to what I posted previously &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2005/10/04/476242.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2005/10/04/476242.aspx"&gt;here&lt;/A&gt; (or what was used in the &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2005/10/25/DebuggerVisualizer-for-DynamicMethod-_2800_Show-me-the-IL_2900_.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2005/10/25/DebuggerVisualizer-for-DynamicMethod-_2800_Show-me-the-IL_2900_.aspx"&gt;DynamicMethod visualizer&lt;/A&gt;), this new version introduced the &lt;A href="http://en.wikipedia.org/wiki/Visitor_pattern" mce_href="http://en.wikipedia.org/wiki/Visitor_pattern"&gt;Visitor pattern&lt;/A&gt;. &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;A do-nothing visitor &lt;SPAN class=inlinecode&gt;ILInstructionVisitor&lt;/SPAN&gt; is included; the users can focus on their domain-specific logic by simply inheriting from it and overriding few methods.&lt;/LI&gt;&lt;/UL&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;public abstract class&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILInstructionVisitor&lt;/SPAN&gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;public virtual void&lt;/SPAN&gt; VisitInlineBrTargetInstruction(&lt;SPAN class=cstype&gt;InlineBrTargetInstruction&lt;/SPAN&gt; inlineBrTargetInstruction) { }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;public virtual void&lt;/SPAN&gt; VisitInlineFieldInstruction(&lt;SPAN class=cstype&gt;InlineFieldInstruction&lt;/SPAN&gt; inlineFieldInstruction) { }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;UL&gt;
&lt;LI&gt;The abstract class &lt;SPAN class=inlinecode&gt;ILInstruction&lt;/SPAN&gt; now has an abstract method "Accept"; each derived ILInstruction class provides the override "Accept" method, which dispatches the call to ILInstructionVisitor's corresponding visit method. It saves a long switch statement when an ILInstruction is about to be processed. &lt;/LI&gt;
&lt;LI&gt;The class &lt;SPAN class=inlinecode&gt;ILReader&lt;/SPAN&gt; has a shortcut to traverse all IL instructions: the instance method "Accept".&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;IMG style="FLOAT: right" height=243 alt="MethodBase Hierarchy" src="http://static.flickr.com/115/290216961_cf7c1184fd_o.jpg" width=406 mce_src="http://static.flickr.com/115/290216961_cf7c1184fd_o.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Class ILReader has 2 overload constructors. There are many mscorlib types derived from MethodBase (see the picture at the right side, from &lt;A href="http://www.aisto.com/roeder/dotnet" mce_href="http://www.aisto.com/roeder/dotnet"&gt;Reflector&lt;/A&gt;); only RuntimeMethodInfo or RuntimeConstructorInfo instance is supposed to pass into the first constructor. Internally it uses &lt;A href="http://msdn2.microsoft.com/de-de/library/system.reflection.methodbase.getmethodbody.aspx" mce_href="http://msdn2.microsoft.com/de-de/library/system.reflection.methodbase.getmethodbody.aspx"&gt;MethodBase.GetMethodBody&lt;/A&gt; and token resolution APIs from &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.module.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.module.aspx"&gt;System.Reflection.Module&lt;/A&gt;. DynamicMethod does not provide public APIs to access the method body, nor the token resolution APIs. &lt;SPAN class=inlinecode&gt;IILProvider&lt;/SPAN&gt; and &lt;SPAN class=inlinecode&gt;ITokenResolver&lt;/SPAN&gt; are designed for easy plug-in of other IL Streams. If you are familar with the DynamicMethod visualizer source code, you already know, for tool authoring purpose, we could use Reflection to reflect some private members (which so depends on the implementation details, and could be likely broken in the future runtime version), and then come up dynamic method related classes (which implement both interfaces). We could figure out how Reflection.Emit manages those tokens at the bake time, but I have not gotten enough time on solving it.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;public&lt;/SPAN&gt; ILReader(&lt;SPAN class=cstype&gt;MethodBase&lt;/SPAN&gt; method);&lt;BR&gt;&lt;SPAN class=cskeyword&gt;public&lt;/SPAN&gt; ILReader(&lt;SPAN class=cstype&gt;IILProvider&lt;/SPAN&gt; ilProvider, &lt;SPAN class=cstype&gt;ITokenResolver&lt;/SPAN&gt; tokenResolver);&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Let us check out how we can build something "useful" with the ILReader. Instead of demo'ing with C# code, I'd like to write some Python code here (well, to promote &lt;A href="http://www.codeplex.com/ironpython" mce_href="http://www.codeplex.com/ironpython"&gt;IronPython &lt;/A&gt;...). &lt;/P&gt;
&lt;P&gt;The first IronPython code examines which System.String's public methods could throw ArgumentOutOfRangeException &lt;EM&gt;directly&lt;/EM&gt;. For that, I can write a ILInstructionVisitor-derived class ThrowExceptionHunter, having one override method VisitInlineMethodInstruction, which checks whether the instructions's operand "Method" belongs to one of ArgumentOutOfRangeException's constructors. In order to stop hunting after hitting the ArgumentOutOfRangeException constructor, I need write a tailored loop, instead of using ILReader.Accept. From the output, we see 11 methods could throw ArgumentOutOfRangeException "directly", and they always call the constructor which requires 2 string arguments (i.e., paramName, message);&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;class&lt;/SPAN&gt; ThrowExceptionHunter(ILInstructionVisitor):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;def&lt;/SPAN&gt; __init__(self, method, exceptionType): &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.method = method&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.ctors = exceptionType.GetConstructors()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.found = False&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;def&lt;/SPAN&gt; VisitInlineMethodInstruction(self, instruction): &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;if&lt;/SPAN&gt; instruction.Method &lt;SPAN class=cskeyword&gt;in&lt;/SPAN&gt; self.ctors:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;print&lt;/SPAN&gt; instruction.Method, &lt;SPAN class=csstring&gt;'|'&lt;/SPAN&gt;, self.method&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.found = True &lt;BR&gt;&lt;BR&gt;clrStringType = clr.GetClrType(System.String)&lt;BR&gt;exceptionType = clr.GetClrType(System.ArgumentOutOfRangeException)&lt;BR&gt;&lt;SPAN class=cskeyword&gt;for&lt;/SPAN&gt; method &lt;SPAN class=cskeyword&gt;in&lt;/SPAN&gt; clrStringType.GetMethods():&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; h = ThrowExceptionHunter(method, exceptionType)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;for&lt;/SPAN&gt; il &lt;SPAN class=cskeyword&gt;in&lt;/SPAN&gt; ILReader(method): &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; il.Accept(h)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;if&lt;/SPAN&gt; h.found: &lt;SPAN class=cskeyword&gt;break&lt;/SPAN&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=typein&gt;Output:&lt;/SPAN&gt;&lt;BR&gt;Void .ctor(System.String, System.String) | System.String Join(System.String, System.String[], Int32, Int32)&lt;BR&gt;...&lt;BR&gt;Void .ctor(System.String, System.String) | System.String Remove(Int32)&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Next visitor is to find callees (methods called by the current method). Early-bind method calls happen with either InlineMethodInstruction or InlineSigInstruction. Suppose you unlikely write code using "calli", only one ILInstructionVisitor method need to be overridden: to put the called method together into a python set (therefore there is no duplicate). The results shows &lt;A href="http://msdn2.microsoft.com/en-us/library/ms131452(VS.80).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms131452(VS.80).aspx"&gt;String.StartsWith(String, StringComparison)&lt;/A&gt; internally used 10 different methods (including constructor call, property access).&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;class&lt;/SPAN&gt; CalleeFinderNoDup(ILInstructionVisitor):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;def&lt;/SPAN&gt; __init__(self):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.callees = set()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;def&lt;/SPAN&gt; VisitInlineMethodInstruction(self, instruction):&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.callees.add(instruction.Method)&lt;BR&gt;&lt;BR&gt;method = clrStringType.GetMethod(&lt;SPAN class=csstring&gt;'StartsWith'&lt;/SPAN&gt;, System.Array[System.Type]([str, System.StringComparison]))&lt;BR&gt;reader = ILReader(method)&lt;BR&gt;&lt;BR&gt;v = CalleeFinderNoDup()&lt;BR&gt;reader.Accept(v)&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print&lt;/SPAN&gt; &lt;SPAN class=csstring&gt;'How many:'&lt;/SPAN&gt;, len(v.callees)&lt;BR&gt;&lt;SPAN class=cskeyword&gt;for&lt;/SPAN&gt; x &lt;SPAN class=cskeyword&gt;in&lt;/SPAN&gt; v.callees: &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;print&lt;/SPAN&gt; x, &lt;SPAN class=csstring&gt;'/'&lt;/SPAN&gt;, x.DeclaringType &lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=typein&gt;Output:&lt;/SPAN&gt;&lt;BR&gt;How many: 10&lt;BR&gt;Void .ctor(System.String) / System.ArgumentNullException&lt;BR&gt;...&lt;BR&gt;Int32 CompareOrdinalIgnoreCaseEx(System.String, Int32, System.String, Int32, Int32) / System.Globalization.TextInfo&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;We can think of many scenarios related to IL code disassembly; the attached ILReader library provides 2 visitors for that purpose: &lt;SPAN class=inlinecode&gt;ReadableILStringVisitor&lt;/SPAN&gt; and &lt;SPAN class=inlinecode&gt;RawILStringVisitor&lt;/SPAN&gt;. Along the visit, we pass in &lt;SPAN class=inlinecode&gt;IILStringCollector&lt;/SPAN&gt;. &lt;SPAN class=inlinecode&gt;ReadableILStringToTextWriter&lt;/SPAN&gt;, which implements IILStringCollector, can be used to dump the readable IL string to the specified TextWriter (shown below). We can write customized ILStringCollectors to collect those IL strings in other manners.&amp;nbsp;&lt;/P&gt;
&lt;DIV class=csharp&gt;v = ReadableILStringVisitor(ReadableILStringToTextWriter(System.Console.Out))&lt;BR&gt;reader.Accept(v)&lt;BR&gt;&lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=typein&gt;Output:&lt;/SPAN&gt;&lt;BR&gt;IL_0000: ldarg.1&lt;BR&gt;IL_0001: brtrue.s IL_000e&lt;BR&gt;IL_0003: ldstr "value"&lt;BR&gt;IL_0008: newobj Void .ctor(System.String)/System.ArgumentNullException&lt;BR&gt;IL_000d: throw&lt;BR&gt;...&lt;BR&gt;IL_00f7: call System.String GetResourceString(System.String)/System.Environment&lt;BR&gt;IL_00fc: ldstr "comparisonType"&lt;BR&gt;IL_0101: newobj Void .ctor(System.String, System.String)/System.ArgumentException&lt;BR&gt;IL_0106: throw&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;By the way, you may think those method names inside the ILInstructionVisitor class are way too long - they all can simply be named "Visit". I agree, actually that was my first try; however to be dynamic language friendly, I renamed them by adding the matching instruction class name. When all methods are named "Visit", static language compiler (like C#) can still decide which method to bind based on the parameter type, while IronPython has to surrender itself to classes derived from such visitor: If we wrote one customized "Visit" method for ThrowExceptionHunter, which base "Visit" method is supposed to override? If you need to override several "Visit" methods from ILInstructionVisitor, there is no way to implement it in Python - defining any amount of "Visit" methods only keeps the last one alive.&lt;/P&gt;
&lt;P&gt;TryILReader.py can be viewed &lt;A class="" href="http://blogs.msdn.com/haibo_luo/pages/try-ilreader.aspx" target=_blank mce_href="http://blogs.msdn.com/haibo_luo/pages/try-ilreader.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;More tools (and discussion) related to this ILReader coming soon. Hope one day this could become System.Reflection.ILReader ...&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Disclaimer: THE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES INTENDED OR IMPLIED. USE AT YOUR OWN RISK&lt;/EM&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1003788" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/1003788.ashx" length="8744" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/IronPython/default.aspx">IronPython</category></item><item><title>Always Peverify IL Code of your Dynamic Method</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/10/31/always-peverify-il-code-of-your-dynamic-method.aspx</link><pubDate>Wed, 01 Nov 2006 07:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1038287</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/1038287.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=1038287</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=1038287</wfw:comment><description>&lt;P&gt;Current dynamic method implementation does not have built-in support to pre-check whether the dynamic method code is verifiable. With bad IL sequence, very often you will get "System.&lt;A href="http://msdn2.microsoft.com/en-us/library/system.invalidprogramexception.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.invalidprogramexception.aspx"&gt;InvalidProgramException&lt;/A&gt;: Common Language Runtime detected an invalid program" when it gets executed. See the code example below, where C1, C2 are 2 simple reference types. Btw I understand only me write such "fun" IL code.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;LocalBuilder&lt;/SPAN&gt; lb = ilgen.DeclareLocal(&lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(C2));&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Newobj, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(C1).GetConstructor(&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.EmptyTypes));&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Stloc_0, lb);&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ldc_I4_0); &lt;BR&gt;ilgen.EmitWriteLine(&lt;SPAN class=csstring&gt;"I got called"&lt;/SPAN&gt;);&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ret);&lt;/DIV&gt;
&lt;P&gt;Even if you did not get InvalidProgramException, it does not mean the code-gen is correct. When the following code get invoked, "I got called too" will be printed; but the code is not verifiable. When the SkipVerification permission is refused, executing this dynamic method causes JIT to verify first: "System.Security.&lt;A href="http://msdn2.microsoft.com/en-us/library/system.security.verificationexception.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.security.verificationexception.aspx"&gt;VerficationException&lt;/A&gt;: Operation could destabilize the runtime" throws. &lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;LocalBuilder&lt;/SPAN&gt; lb = ilgen.DeclareLocal(&lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(C2));&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Newobj, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(C1).GetConstructor(&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.EmptyTypes));&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Stloc_0, lb);&lt;BR&gt;ilgen.EmitWriteLine(&lt;SPAN class=csstring&gt;"I got called too"&lt;/SPAN&gt;);&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ret);&lt;/DIV&gt;
&lt;P&gt;However both exception messages contain no much useful information: they do not tell which instruction could be blamed. For any production code using DynamicMethod, to ensure the code-gen quality, it is a good practice to have another implementation which have Reflection.Emit to emit the same IL code to disk, and call Peverify.exe to verify it. &lt;A href="http://www.codeplex.com/ironpython" mce_href="http://www.codeplex.com/ironpython"&gt;IronPython&lt;/A&gt;'s code-gen has both approaches: at the beginning when we enforced this check, we caught several code-gen issues. This is what peverify.exe shows for the 2 scenarios above:&lt;/P&gt;
&lt;DIV class=csharp&gt;[IL]: Error: [D:\snippets.dll : Sample::M][offset 0x00000005][found ref 'C1'][expected ref 'C2'] Unexpected type on the stack.&lt;BR&gt;[IL]: Error: [D:\snippets.dll : Sample::M][offset 0x00000011] Stack must be empty on return from a void function.&lt;BR&gt;----&lt;BR&gt;[IL]: Error: [D:\snippets.dll : Sample::M][offset 0x00000005][found ref 'C1'][expected ref 'C2'] Unexpected type on the stack.&lt;BR&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1038287" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection.Emit/default.aspx">Reflection.Emit</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>ILGenerator.EmitCall Mainly For vararg Methods</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/08/13/698719.aspx</link><pubDate>Mon, 14 Aug 2006 02:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:698719</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/698719.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=698719</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=698719</wfw:comment><description>&lt;P&gt;Vararg (variable arguments) methods accept argument lists of unknown length and type. CLR supports this by the IL instruction (arglist) and other BCL types, such as &lt;A href="http://msdn2.microsoft.com/en-US/library/System.ArgIterator.aspx"&gt;System.ArgIterator&lt;/A&gt;. C# compiler has undocumented keyword "__arglist" to support defining vararg methods, accessing variable arguments and calling them, as shown below. &lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;static void&lt;/SPAN&gt; VarargMethod(&lt;SPAN class=cskeyword&gt;string&lt;/SPAN&gt; headline, &lt;SPAN class=cskeyword&gt;__arglist&lt;/SPAN&gt;) {&lt;BR&gt;&amp;nbsp; &lt;SPAN class=cskeyword&gt;ArgIterator&lt;/SPAN&gt; ai = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ArgIterator&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;__arglist&lt;/SPAN&gt;);&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp; &lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.Write(headline);&lt;BR&gt;&amp;nbsp; &lt;SPAN class=cskeyword&gt;while&lt;/SPAN&gt; (ai.GetRemainingCount() &amp;gt; 0)&lt;BR&gt;&amp;nbsp; &amp;nbsp; &lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN class=cstype&gt;TypedReference&lt;/SPAN&gt;.ToObject(ai.GetNextArg()));&lt;BR&gt;&amp;nbsp; &amp;nbsp; &lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.WriteLine();&lt;BR&gt;}&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;static void&lt;/SPAN&gt; CallVarargMethod() {&lt;BR&gt;&amp;nbsp; VarargMethod(&lt;SPAN class=csstring&gt;"Hello world from "&lt;/SPAN&gt;, &lt;SPAN class=cskeyword&gt;__arglist&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;Assembly&lt;/SPAN&gt;.GetExecutingAssembly()));&lt;BR&gt;&amp;nbsp; VarargMethod(&lt;SPAN class=csstring&gt;"Current time: "&lt;/SPAN&gt;, &lt;SPAN class=cskeyword&gt;__arglist&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;.Now, &lt;SPAN class=csstring&gt;" (UTC "&lt;/SPAN&gt;, &lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;.UtcNow, &lt;SPAN class=csstring&gt;")"&lt;/SPAN&gt;));&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Two&amp;nbsp;MemberRef tokens are needed to specify each vararg method call site. The blob each MemberRef points to specifies the methodref signature: types of both fixed and variable arguments. &lt;/P&gt;
&lt;DIV class=ilcode&gt;MethodName: VarargMethod (06000001)&lt;BR&gt;MemberRef #1 (0a00000c)&lt;BR&gt;&amp;nbsp; &amp;nbsp; 2 Arguments&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #1: String&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #2: &amp;lt;ELEMENT_TYPE_SENTINEL&amp;gt; Class System.Reflection.Assembly&lt;BR&gt;MemberRef #2 (0a00000f)&lt;BR&gt;&amp;nbsp; &amp;nbsp; 5 Arguments&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #1: String&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #2: &amp;lt;ELEMENT_TYPE_SENTINEL&amp;gt; ValueClass System.DateTime&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #3: String&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #4: ValueClass System.DateTime&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #5: String&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-US/library/system.reflection.emit.ilgenerator.emitcall.aspx"&gt;ILGenerator.EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)&lt;/A&gt; is designed for emitting call to such vararg method (for both Reflection.Emit and dynamic method scenarios). The optionalParameterTypes argument is passed in to create different MethodRef tokens. &lt;/P&gt;
&lt;P&gt;Assume the MethodInfo of "VarargMethod" is miVarargMethod, the following code creates a DynamicMethod to perform the same functionality as previous "CallVarargMethod" does:&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;DynamicMethod&lt;/SPAN&gt; dm = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;DynamicMethod&lt;/SPAN&gt;(&lt;SPAN class=csstring&gt;"CallVarargMethod"&lt;/SPAN&gt;, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;void&lt;/SPAN&gt;), &lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.EmptyTypes, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;object&lt;/SPAN&gt;));&lt;BR&gt;&lt;SPAN class=cstype&gt;ILGenerator&lt;/SPAN&gt; il = dm.GetILGenerator();&lt;BR&gt;&amp;nbsp;&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ldstr, &lt;SPAN class=csstring&gt;"Hello world from "&lt;/SPAN&gt;);&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;Assembly&lt;/SPAN&gt;).GetMethod(&lt;SPAN class=csstring&gt;"GetExecutingAssembly"&lt;/SPAN&gt;));&lt;BR&gt;il.EmitCall(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, miVarargMethod, &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;Assembly&lt;/SPAN&gt;) });&lt;BR&gt;&amp;nbsp;&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ldstr, &lt;SPAN class=csstring&gt;"Current time: "&lt;/SPAN&gt;);&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;).GetMethod(&lt;SPAN class=csstring&gt;"get_Now"&lt;/SPAN&gt;));&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ldstr, &lt;SPAN class=csstring&gt;" (UTC "&lt;/SPAN&gt;);&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;).GetMethod(&lt;SPAN class=csstring&gt;"get_UtcNow"&lt;/SPAN&gt;));&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ldstr, &lt;SPAN class=csstring&gt;")"&lt;/SPAN&gt;);&lt;BR&gt;il.EmitCall(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, miVarargMethod, &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;), &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;string&lt;/SPAN&gt;), &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;), &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;string&lt;/SPAN&gt;) });&lt;BR&gt;&amp;nbsp;&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ret);&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;As you see in the attached C# code (which uses ILGenerator.EmitCall for both Reflection.Emit and DynamicMethod), Type.GetMethod (and other APIs) can return MethodInfo of vararg methods; however &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbase.invoke.aspx "&gt;MethodInfo.Invoke&lt;/A&gt; currently does not support to invoke on them. It is easy to get around with this: just&amp;nbsp;create a dynamic method, and use EmitCall, and invoke on the dynamic method.&lt;/P&gt;
&lt;P&gt;Although EmitCall can be used to emit a call to non-vararg method, you are encouraged to use &lt;A href="http://msdn2.microsoft.com/en-us/library/xz8067x2.aspx"&gt;ILGenerator.Emit(OpCode, MethodInfo)&lt;/A&gt; for that scenario, and use EmitCall mainly for vararg methods. With that said, the naming of this API does sound somewhat misleading. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=698719" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/698719.ashx" length="2807" type="text/plain" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection.Emit/default.aspx">Reflection.Emit</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>Hello World with DynamicILInfo</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx</link><pubDate>Tue, 31 Jan 2006 04:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:519984</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/519984.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=519984</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=519984</wfw:comment><description>    &lt;p&gt;
        The following &amp;quot;Hello World&amp;quot; program shows how to use APIs in the class
        &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.aspx"&gt;
            DynamicILInfo&lt;/a&gt;. MSDN documentation will have more details on this class in
        the next release.&lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;using&lt;/span&gt; System;&lt;br /&gt;
        &lt;span class="cskeyword"&gt;using &lt;/span&gt;System.Reflection;&lt;br /&gt;
        &lt;span class="cskeyword"&gt;using &lt;/span&gt;System.Reflection.Emit;&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &lt;span class="cskeyword"&gt;class &lt;/span&gt;&lt;span class="cstype"&gt;Demo &lt;/span&gt;{&lt;br /&gt;
        &amp;nbsp; &lt;span class="cskeyword"&gt;static void &lt;/span&gt;Main() {&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;DynamicMethod &lt;/span&gt;dm = &lt;span class="cskeyword"&gt;
            new &lt;/span&gt;&lt;span class="cstype"&gt;DynamicMethod&lt;/span&gt;(&lt;span class="csstring"&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;,
        &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;void&lt;/span&gt;), &lt;span
            class="cstype"&gt;Type&lt;/span&gt;.EmptyTypes, &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(Demo),
        &lt;span class="cskeyword"&gt;false&lt;/span&gt;);&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;DynamicILInfo &lt;/span&gt;il = dm.GetDynamicILInfo();&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;SignatureHelper &lt;/span&gt;sigHelper = &lt;span
            class="cstype"&gt;SignatureHelper&lt;/span&gt;.GetLocalVarSigHelper();&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; il.SetLocalSignature(sigHelper.GetSignature());&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="cskeyword"&gt;byte&lt;/span&gt;[] code = { 0x00, 0x72, &lt;strong&gt;
            0x01, 0x00, 0x00, 0x70&lt;/strong&gt;, 0x28, &lt;strong&gt;0x04, 0x00, 0x00, 0x0a&lt;/strong&gt;,
        0x00, 0x2a };&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;int &lt;/span&gt;token0 = il.GetTokenFor(&lt;span
            class="csstring"&gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;);&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;int &lt;/span&gt;token1 = il.GetTokenFor(&lt;span
            class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;Console&lt;/span&gt;).GetMethod(&lt;span
                class="csstring"&gt;&amp;quot;WriteLine&amp;quot;&lt;/span&gt;, new Type[] { &lt;span class="cskeyword"&gt;
                    typeof&lt;/span&gt;(&lt;span class="cskeyword"&gt;string&lt;/span&gt;) }).MethodHandle);&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; PutInteger4(token0, 0x0002, code);&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; PutInteger4(token1, 0x0007, code);&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; il.SetCode(code, 8);&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; dm.Invoke(&lt;span class="cskeyword"&gt;null&lt;/span&gt;, &lt;span class="cskeyword"&gt;
            null&lt;/span&gt;);&lt;br /&gt;
        &amp;nbsp; }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &lt;span class="cskeyword"&gt;static void&lt;/span&gt; PutInteger4(&lt;span class="cskeyword"&gt;int
        &lt;/span&gt;value, &lt;span class="cskeyword"&gt;int &lt;/span&gt;startPos, &lt;span class="cskeyword"&gt;byte&lt;/span&gt;[]
        array) {&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &amp;nbsp;array[startPos++] = (&lt;span class="cskeyword"&gt;byte&lt;/span&gt;)value;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; array[startPos++] = (&lt;span class="cskeyword"&gt;byte&lt;/span&gt;)(value
        &amp;gt;&amp;gt; 8);&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; array[startPos++] = (&lt;span class="cskeyword"&gt;byte&lt;/span&gt;)(value
        &amp;gt;&amp;gt; 16);&lt;br /&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp; array[startPos++] = (&lt;span class="cskeyword"&gt;byte&lt;/span&gt;)(value
        &amp;gt;&amp;gt; 24);&lt;br /&gt;
        &amp;nbsp; }&lt;br /&gt;
        }&lt;/div&gt;
    &lt;div class="csharp"&gt;
        &amp;gt; &lt;span class="typein"&gt;csc.exe demo.cs&lt;/span&gt;&lt;br /&gt;
        &amp;gt; &lt;span class="typein"&gt;demo&lt;/span&gt;&lt;br /&gt;
        Hello world&lt;br /&gt;
    &lt;/div&gt;
    &lt;p&gt;
        The DynamicILInfo class is different from &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.ilgenerator.aspx"&gt;
            ILGenerator&lt;/a&gt;. It &lt;strong&gt;directly&lt;/strong&gt; uses byte arrays to set IL code,
        exception, and the local signature. So how can we get those byte arrays?
    &lt;/p&gt;
    &lt;p&gt;
        If the dynamic method we are going to create is based on a static method in some
        existing assembly, we can view the IL code (bytes) of the static method via ildasm
        or by using &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.aspx"&gt;
            MethodBody&lt;/a&gt;.&lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.getilasbytearray.aspx"&gt;GetILByteArray&lt;/a&gt;.
        We can then build the byte array for SetCode from there. For all tokens used in
        the original static method, be sure to replace them (bold, as shown above and below
        in this example) with those generated from GetTokenFor.&amp;nbsp;&lt;/p&gt;
    &lt;div class="ilcode"&gt;
        .method public hidebysig static void HelloWorld() cil managed&lt;br /&gt;
        // SIG: 00 00 01&lt;br /&gt;
        {&lt;br /&gt;
        &amp;nbsp; // Method begins at RVA 0x2050&lt;br /&gt;
        &amp;nbsp; // Code size 13 (0xd)&lt;br /&gt;
        &amp;nbsp; .maxstack 8&lt;br /&gt;
        &amp;nbsp; IL_0000: /* 00 |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
        */ nop&lt;br /&gt;
        &amp;nbsp; IL_0001: /* 72 | &lt;strong&gt;(70)000001&lt;/strong&gt; */ ldstr "Hello world"&lt;br /&gt;
        &amp;nbsp; IL_0006: /* 28 | &lt;strong&gt;(0A)000004&lt;/strong&gt; */ call void [mscorlib]System.Console::WriteLine(string)&lt;br /&gt;
        &amp;nbsp; IL_000b: /* 00 |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
        */ nop&lt;br /&gt;
        &amp;nbsp; IL_000c: /* 2A |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
        */ ret&lt;br /&gt;
        }
    &lt;/div&gt;
    &lt;p&gt;
        To build the byte array for SetException, I'd suggest taking a couple of minutes
        to read &lt;a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm"&gt;
            ECMA spec&lt;/a&gt; partiton II (25.4.6) first. The Flags/TryOffset/TryLength/HandlerOffset/HandlerLength
        ... can be retrieved from MethodBody.&lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.exceptionhandlingclauses.aspx"&gt;ExceptionHandlingClauses&lt;/a&gt;
        programatically. Be aware the exception type token (ClassToken) has to be obtained
        from &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.gettokenfor.aspx"&gt;
            GetTokenFor&lt;/a&gt; as well. Do you know Ildasm can show the raw exception information?
        I did not know this until I learned about it recently from &lt;a href="http://blog.dotnetwiki.org/"&gt;
            Peli&lt;/a&gt;.:) Uncheck View-&amp;gt;Expand try/catch and check show bytes; we will
        see something like the following at the bottom of the method IL:
    &lt;/p&gt;
    &lt;div class="ilcode"&gt;
        &amp;nbsp; // Exception count 1
        &lt;br /&gt;
        &amp;nbsp; .try IL_002e to IL_0051 finally handler IL_0051 to IL_0065&lt;br /&gt;
        &amp;nbsp; // HEX: 02 00 00 00 2E 00 00 00 23 00 00 00 51 00 00 00 14 00 00 00 00 00
        00 00&lt;br /&gt;
        }
    &lt;/div&gt;
    &lt;p&gt;
        Class &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.signaturehelper.aspx"&gt;
            SignatureHelper&lt;/a&gt; offers a convenient way to construct the local variable
        signature, if each local variable type is known. We can just make calls of SignatureHelper.&lt;a
            href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.signaturehelper.addargument.aspx"&gt;AddArgument&lt;/a&gt;.&lt;/p&gt;
    &lt;p&gt;
        Are there any scenarios in your mind where using DynamicILInfo could be better than
        using DynamicILGenerator? How'd you like to construct those byte arrays? I am thinking
        about writing and sharing a tool, which, based on an existing method, generates
        C# code to define the equivalent dynamic method (using DynamicILInfo) (if this turns
        out to be a popular scenario).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=519984" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>Activator.CreateInstance and beyond</title><link>http://blogs.msdn.com/haibo_luo/archive/2005/11/17/494009.aspx</link><pubDate>Thu, 17 Nov 2005 21:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:494009</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/494009.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=494009</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=494009</wfw:comment><description>&lt;P&gt;&lt;B&gt;Q&lt;/B&gt;: Assume we have 2000 unknown types; (however) we know each type has a constructor with integer as its' only parameter type. How to create objects 10000 times for each type (and make such late-new fast)? &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/system.Activator.CreateInstance.aspx"&gt;Activator.CreateInstance&lt;/A&gt;&lt;/STRONG&gt; comes to my fingers first. It is just so convenient to use: calling Activator.CreateInstance(&lt;EM&gt;type&lt;/EM&gt;, new object[] {100}) in a loop. Done... I already heard somebody is yelling "this API is slow" ;) Yeah, each time it need figure out the right ConstructorInfo (by calling GetConstructors to get all ctors, parsing the constructor method signature/comparing, and binding to the most matched one). If you happen to have &lt;A href="http://msdn.microsoft.com/teamsystem/"&gt;Visual Studio Team System&lt;/A&gt; installed, you can use &lt;A HREF="/haibo_luo/articles/494008.aspx"&gt;this code&lt;/A&gt; to do a sample profiling and see what is going on there.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;Activator&lt;/SPAN&gt;.CreateInstance(type, 100); &lt;/DIV&gt;
&lt;P&gt;&lt;STRONG&gt;Reflection Emit&lt;/STRONG&gt; can optimize this scenario a bit: we create an in-memory module and a helper class "ClassFactory", then define one helper method for each type with the early-bind call (strong typed new, see OpCodes.Newobj below); the emitted method is equivalent to "&lt;SPAN class=inlinecode&gt;public static &lt;EM&gt;Type&lt;/EM&gt; &lt;EM&gt;TypeName&lt;/EM&gt;(int arg1){ return new &lt;EM&gt;Type&lt;/EM&gt;(arg1); }&lt;/SPAN&gt;" in C#.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;AssemblyBuilder &lt;/SPAN&gt;asmBldr = &lt;SPAN class=cstype&gt;AppDomain&lt;/SPAN&gt;.CurrentDomain.DefineDynamicAssembly(new &lt;SPAN class=cstype&gt;AssemblyName&lt;/SPAN&gt;(&lt;SPAN class=csstring&gt;"InMemory"&lt;/SPAN&gt;), &lt;SPAN class=cstype&gt;AssemblyBuilderAccess&lt;/SPAN&gt;.Run);&lt;BR&gt;&lt;SPAN class=cstype&gt;ModuleBuilder &lt;/SPAN&gt;modBldr = asmBldr.DefineDynamicModule(&lt;SPAN class=csstring&gt;"helper"&lt;/SPAN&gt;);&lt;BR&gt;&lt;SPAN class=cstype&gt;TypeBuilder &lt;/SPAN&gt;typeBldr = modBldr.DefineType(&lt;SPAN class=csstring&gt;"ClassFactory"&lt;/SPAN&gt;);&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;MethodBuilder &lt;/SPAN&gt;methBldr = typeBldr.DefineMethod(type.Name, &lt;SPAN class=cstype&gt;MethodAttributes&lt;/SPAN&gt;.Public | &lt;SPAN class=cstype&gt;MethodAttributes&lt;/SPAN&gt;.Static, type, &lt;SPAN class=cskeyword&gt;new &lt;/SPAN&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;) });&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;ILGenerator &lt;/SPAN&gt;ilgen = methBldr.GetILGenerator();&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Nop);&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ldarg_1);&lt;/EM&gt; &lt;BR&gt;&lt;EM&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.&lt;B&gt;Newobj&lt;/B&gt;, type.GetConstructor(&lt;SPAN class=cskeyword&gt;new &lt;/SPAN&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;) }));&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ret);&lt;/EM&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cstype&gt;Type &lt;/SPAN&gt;baked = typeBldr.CreateType();&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;MethodInfo &lt;/SPAN&gt;mi = baked.GetMethod(type.Name);&lt;/EM&gt; &lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;EM&gt;mi.Invoke(&lt;SPAN class=cskeyword&gt;null&lt;/SPAN&gt;, &lt;SPAN class=cskeyword&gt;new object&lt;/SPAN&gt;[] { 100 });&lt;/EM&gt;&lt;/DIV&gt;
&lt;P&gt;The code in italic need be put in a loop to repeat on 2000 types. We cache the MethodInfo (after baked) to a Dictionary&amp;lt;Type, MethodInfo&amp;gt; so that we can quickly retrieve the MethodInfo for massive consequent Invoke calls.&lt;/P&gt;
&lt;P&gt;With &lt;STRONG&gt;DynamicMethod&lt;/STRONG&gt; in CLR 2.0, we can avoid that lengthy preparation and bake steps (yes, light-weight codegen). For each type, simply create one dynamic method with the early-bind &lt;EM&gt;newobj&lt;/EM&gt;, and cache it for future use.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;DynamicMethod &lt;/SPAN&gt;dm = new &lt;SPAN class=cstype&gt;DynamicMethod&lt;/SPAN&gt;(&lt;SPAN class=csstring&gt;"MyCtor"&lt;/SPAN&gt;, type, &lt;SPAN class=cskeyword&gt;new &lt;/SPAN&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;) }, typeof(&lt;SPAN class=cstype&gt;LateNew&lt;/SPAN&gt;).Module);&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;ILGenerator &lt;/SPAN&gt;ilgen = dm.GetILGenerator();&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ldarg_1);&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Newobj, type.GetConstructor(&lt;SPAN class=cskeyword&gt;new &lt;/SPAN&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;) }));&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ret);&lt;/EM&gt; &lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;EM&gt;dm.Invoke(&lt;SPAN class=cskeyword&gt;null&lt;/SPAN&gt;, &lt;SPAN class=cskeyword&gt;new object&lt;/SPAN&gt;[] { 100 });&lt;/EM&gt; &lt;/DIV&gt;
&lt;P&gt;Do not forget &lt;STRONG&gt;ConstructorInfo.Invoke&lt;/STRONG&gt;. This approach caches the RuntimeConstructorInfo of the &lt;EM&gt;exact&lt;/EM&gt; constructor which we can then invoke on directly; on the other hand, previous Emit/DynamicMethod approaches seemly add one more layer late-invocation.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;ConstructorInfo &lt;/SPAN&gt;ci = t.GetConstructor(&lt;SPAN class=cskeyword&gt;new &lt;/SPAN&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;) });&lt;/EM&gt; &lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;EM&gt;ci.Invoke(&lt;SPAN class=cskeyword&gt;new object&lt;/SPAN&gt;[] { 100 });&lt;/EM&gt; &lt;/DIV&gt;
&lt;P&gt;If you subsribe Joel Pobar's blog , you may already notice &lt;A HREF="/joelpob/archive/2004/04/01/105862.aspx"&gt;"delegate call in whidbey is close to callvirt in term of performance"&lt;/A&gt;. Instead of caching the baked MethodInfo (or DynamicMethod), we should spend a bit more time on the preparation stage: to create the delegate (function pointer) for those on-the-fly methods and cache them . Assume I already defined such helper delegate type as follows:&lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;nbsp;&lt;SPAN class=cskeyword&gt;public delegate object&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;CtorInt32Delegate&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;int &lt;/SPAN&gt;arg); &lt;/DIV&gt;
&lt;P&gt;Let's call next approach as &lt;STRONG&gt;Reflection.Emit+Delegate&lt;/STRONG&gt;, we can leverage those codes for the Reflection Emit approach above, and add one line of code to create the delegate:&lt;/P&gt;
&lt;DIV class=csharp&gt;...&lt;BR&gt;&lt;SPAN class=cstype&gt;Type &lt;/SPAN&gt;baked = typeBldr.CreateType();&lt;BR&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;MethodInfo &lt;/SPAN&gt;mi = baked.GetMethod(type.Name);&lt;/EM&gt; &lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;CtorInt32Delegate &lt;/SPAN&gt;d = (&lt;SPAN class=cstype&gt;CtorInt32Delegate&lt;/SPAN&gt;)&lt;SPAN class=cstype&gt;Delegate&lt;/SPAN&gt;.CreateDelegate(&lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;CtorInt32Delegate&lt;/SPAN&gt;), mi);&lt;/EM&gt; &lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;EM&gt;d(100);&amp;nbsp; &lt;SPAN class=cscomment&gt;// C# syntax shortcut to d.Invoke(100);&lt;/SPAN&gt;&lt;/EM&gt;&lt;/DIV&gt;
&lt;P&gt;We do the similar thing for the &lt;STRONG&gt;DynamicMethod + Delegate&lt;/STRONG&gt; approach :&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;EM&gt;&lt;SPAN class=cstype&gt;DynamicMethod &lt;/SPAN&gt;dm = new &lt;SPAN class=cstype&gt;DynamicMethod&lt;/SPAN&gt;(&lt;SPAN class=csstring&gt;"MyCtor"&lt;/SPAN&gt;, type, &lt;SPAN class=cskeyword&gt;new &lt;/SPAN&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;) }, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;LateNew&lt;/SPAN&gt;).Module);&lt;/EM&gt;&lt;BR&gt;&lt;EM&gt;&lt;SPAN class=cscomment&gt;// get ILGenerator, and Emit call squences&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cstype&gt;CtorInt32Delegate &lt;/SPAN&gt;d = (&lt;SPAN class=cstype&gt;CtorInt32Delegate&lt;/SPAN&gt;)dm.CreateDelegate(&lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;CtorInt32Delegate&lt;/SPAN&gt;));&lt;/EM&gt; &lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;EM&gt;d(100); &lt;/EM&gt;&lt;/DIV&gt;
&lt;P&gt;The following table lists the result of&amp;nbsp; these 6 approaches (no doubt there are other good solutions to the original question) when running the test code at my machine: the 2nd column shows the preparation time (code in the first box of each pair); the 3rd column is the object creation time cost (the second box). Among them, the last 2 approaches show the best performance. If you are wondering the early-bind cost for the same task, it is roughly 1 second at my machine.&lt;/P&gt;
&lt;TABLE id=table5 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;B&gt;Approach&lt;/B&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;B&gt;Preparation Time(sec)&lt;/B&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;B&gt;Object Creation Time (sec)&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;Activator.CreateInstance&lt;/TD&gt;
&lt;TD&gt;--&lt;/TD&gt;
&lt;TD&gt;00:09:28.4796646&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;Reflection.Emit&lt;/TD&gt;
&lt;TD&gt;00:00:01.5781553&lt;/TD&gt;
&lt;TD&gt;00:02:28.7684813&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;DynamicMethod.Invoke&lt;/TD&gt;
&lt;TD&gt;00:00:00.0781265&lt;/TD&gt;
&lt;TD&gt;00:02:04.3930133&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;ConstructorInfo.Invoke&lt;/TD&gt;
&lt;TD&gt;00:00:00.0468759&lt;/TD&gt;
&lt;TD&gt;00:00:56.0167005&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;Reflection.Emit+Delegate&lt;/TD&gt;
&lt;TD&gt;00:00:01.4218750&lt;/TD&gt;
&lt;TD&gt;00:00:04.2968750&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;DynamicMethod+Delegate&lt;/TD&gt;
&lt;TD&gt;00:00:00.1093771&lt;/TD&gt;
&lt;TD&gt;00:00:05.7031250&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;What if the constructor is parameterless? Here is the result (side by side with previous scenario, the object creation cost listed):&lt;/P&gt;
&lt;TABLE id=table6 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style="HEIGHT: 21px"&gt;&lt;B&gt;Approach&lt;/B&gt;&lt;/TD&gt;
&lt;TD style="HEIGHT: 21px"&gt;&lt;B&gt;Parameterless &lt;/B&gt;&lt;/TD&gt;
&lt;TD style="HEIGHT: 21px"&gt;&lt;B&gt;Parameter&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD style="HEIGHT: 21px"&gt;Activator.CreateInstance&lt;/TD&gt;
&lt;TD style="HEIGHT: 21px"&gt;&lt;STRONG&gt;00:00:54.1729151&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD style="HEIGHT: 21px"&gt;00:09:28.4796646&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;Reflection.Emit&lt;/TD&gt;
&lt;TD&gt;00:02:10.3775032&lt;/TD&gt;
&lt;TD&gt;00:02:28.7684813&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;DynamicMethod.Invoke&lt;/TD&gt;
&lt;TD&gt;00:01:37.6581250&lt;/TD&gt;
&lt;TD&gt;00:02:04.3930133&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;ConstructorInfo.Invoke&lt;/TD&gt;
&lt;TD&gt;00:00:44.1883484&lt;/TD&gt;
&lt;TD&gt;00:00:56.0167005&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;Reflection.Emit+Delegate&lt;/TD&gt;
&lt;TD&gt;00:00:04.3125000&lt;/TD&gt;
&lt;TD&gt;00:00:04.2968750&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;DynamicMethod+Delegate&lt;/TD&gt;
&lt;TD&gt;00:00:05.5313562 &lt;/TD&gt;
&lt;TD&gt;00:00:05.7031250&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;We noticed:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Activator.CreateInstance approach is actually not that bad here: this API has different path to handle parameterless scenarios. 
&lt;LI&gt;No significant differences between these 2 scenarios for other 5 approaches. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Furthermore, if only less than 16 types are frequently used, Activator.CreateInstance is "fast" API: &amp;nbsp;internally it creates some sort of delegate directly on the type's parameterless constructor (no dynamic generated methods involved), and cache them. However, the cache size is 16, and 'Least Recently Used'-like cache algorithm is applied. The table below shows the time cost for creating objects of 16 or 17 different types sequentially 2000000 times.&lt;/P&gt;
&lt;TABLE id=table7 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;B&gt;# types used &lt;/B&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;B&gt;&amp;nbsp;Call Activator.CreateInstance(Type type) &lt;/B&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;B&gt;Reflection.Emit+Delegate&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;16&lt;/TD&gt;
&lt;TD&gt;00:00:10.8439582&lt;/TD&gt;
&lt;TD&gt;00:00:01.5156541 + 00:00:04.2344563&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;17&lt;/TD&gt;
&lt;TD&gt;00:01:27.6110571&lt;/TD&gt;
&lt;TD&gt;00:00:01.5312794 + 00:00:04.4844611&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=494009" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection.Emit/default.aspx">Reflection.Emit</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>DebuggerVisualizer for DynamicMethod (Show me the IL)</title><link>http://blogs.msdn.com/haibo_luo/archive/2005/10/25/DebuggerVisualizer-for-DynamicMethod-_2800_Show-me-the-IL_2900_.aspx</link><pubDate>Wed, 26 Oct 2005 00:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:484861</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/484861.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=484861</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=484861</wfw:comment><description>&lt;P&gt;Have you ever tried DynamicMethod, one of the coolest features in the .NET 2.0? Hope you have; otherwise, you can try it now with the examples &lt;A href="http://blogs.msdn.com/joelpob/archive/2004/03/31/105282.aspx" mce_href="http://blogs.msdn.com/joelpob/archive/2004/03/31/105282.aspx"&gt;1&lt;/A&gt;, &lt;A href="http://blogs.msdn.com/joelpob/archive/2004/04/01/105862.aspx" mce_href="http://blogs.msdn.com/joelpob/archive/2004/04/01/105862.aspx"&gt;2&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;Like emitting IL to MethodBuilder, we first get ILGenerator from a DynamicMethod, and make a series of ILGenerator.Emit calls to emit the IL instructions. If the emit sequence/logic is complicated, we are likely to wanna check the on-the-fly IL content when debugging. (In fact, class &lt;I&gt;DynamicILInfo&lt;/I&gt; provides an alternative way to set the IL code for dynamic method.) &lt;/P&gt;
&lt;P&gt;It is not straightforward to find out this information and show it. Those instructions are stored in a byte array, so we need an ILReader to parse it; if the ILDasm-style output is preferred, we need to resolve type/field/method back from tokens (DynamicMethod has its own token management mechanism). By the way, Yiru wrote an excellent post "&lt;A href="http://blogs.msdn.com/yirutang/archive/2005/05/26/422373.aspx" mce_href="http://blogs.msdn.com/yirutang/archive/2005/05/26/422373.aspx"&gt;Debugging LCG&lt;/A&gt;", where windbg + SOS were used, and !dumpil was called with the DynamicMethod's MethodDesc (which is not available until jit'ting) &lt;/P&gt;
&lt;P&gt;What if we want to live with the nice-looking Visual Studio 2005 environment, and still be able to see what has been emitted by far while we are debugging the dynamic method? &lt;A href="http://blog.dotnetwiki.org/" mce_href="http://blog.dotnetwiki.org/"&gt;Peli&lt;/A&gt; (our CLR team member and also an active Emit/LCG user) proposed that DebuggerVisualizer is a good solution. If you are interested in DebuggerVisualizer in general, some references can be found at &lt;A href="http://blogs.msdn.com/scottno/archive/category/10107.aspx" mce_href="http://blogs.msdn.com/scottno/archive/category/10107.aspx"&gt;Scott's blog&lt;/A&gt; (or msdn: &lt;A href="http://search.msn.com/results.aspx?q=msdn+how+to+write+visualizer" mce_href="http://search.msn.com/results.aspx?q=msdn+how+to+write+visualizer"&gt;how to write a visualizer&lt;/A&gt;) &lt;/P&gt;
&lt;P&gt;Introducing my DynamicMethod DebuggerVisualizer... here are some visualizer-in-action pictures: &lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT: black 1pt solid; BORDER-TOP: black 1pt solid; BORDER-LEFT: black 1pt solid; BORDER-BOTTOM: black 1pt solid" alt=pic1 src="http://static.flickr.com/25/51647545_8b3b618a49_o.gif" mce_src="http://static.flickr.com/25/51647545_8b3b618a49_o.gif"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT: black 1pt solid; BORDER-TOP: black 1pt solid; BORDER-LEFT: black 1pt solid; BORDER-BOTTOM: black 1pt solid" alt=pic2 src="http://static.flickr.com/31/51647546_d546579837_o.gif" mce_src="http://static.flickr.com/31/51647546_d546579837_o.gif"&gt;&lt;/P&gt;
&lt;P&gt;We can launch the visualizer dialog by clicking the magnifying glass visualizer button, from the local/watch windows or any DynamicMethod variable's data tip. &lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT: black 1pt solid; BORDER-TOP: black 1pt solid; BORDER-LEFT: black 1pt solid; BORDER-BOTTOM: black 1pt solid" alt=pic3 src="http://static.flickr.com/38/84010984_f6fc2ed779_o.gif" mce_src="http://static.flickr.com/38/84010984_f6fc2ed779_o.gif"&gt;&lt;/P&gt;
&lt;P&gt;This is my DynamicMethod DebuggerVisualizer dialog window. The main area shows the IL we emitted so far. "Show bytes" checkbox allows us to specify whether we want to see the raw byte data. The window size/position and other settings are saved in the registry (unfortunately). &lt;/P&gt;
&lt;P&gt;It contains two dlls: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;B&gt;DynamicMethodVisualizer&lt;/B&gt;: Just some routine debugger visualizer code here. Since DynamicMethod is not serializable, I have to prepare all necessary info in the debuggee side first, and save them into my MethodBodyInfo class. All IL instructions turn into the string format. No doubt, there are some side-effects on the the debuggee side. 
&lt;LI&gt;&lt;B&gt;ILReader&lt;/B&gt;: I mentioned a Reflection-based ILReader implementation in my &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2005/10/02/476242.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2005/10/02/476242.aspx"&gt;previous post&lt;/A&gt;. In addition we need know some DynamicMethod implementation details (you can sleuth it using &lt;A href="http://www.aisto.com/roeder/dotnet" mce_href="http://www.aisto.com/roeder/dotnet"&gt;Reflector&lt;/A&gt; or Rotor 2.0 source code in the future): the internal m_ILStream field in class &lt;I&gt;DynamicILGenerateor&lt;/I&gt; is used to store IL instructions; another class &lt;I&gt;DynamicScope&lt;/I&gt; is to keep track of those used tokens. In order to retrieve the byte array and to resolve those tokens to some meaningful members, reflection APIs (such as FieldInfo.GetValue, PropertyInfo.GetValue etc) are used to explore those internal fields; &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;LEGAL NOTE: All source code is provided as is, with no warranties intended or implied. Use at your own risk. &lt;/P&gt;
&lt;P&gt;Also, the implementation depends on internal DynamicMethod implementation, and does not ensure continuing working in the future. Such approach is not recommended for any production code either. &lt;/P&gt;
&lt;P&gt;You may download the source code and binaries &lt;A href="http://gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=22BA8210-B3A0-4580-B362-ABC7C1A59C65" mce_href="http://gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=22BA8210-B3A0-4580-B362-ABC7C1A59C65"&gt;here&lt;/A&gt; at gotdotnet.com (which also includes a visualizer test program). To let this visualizer help your DynamicMethod debugging, (build &amp;amp;) copy DynamicMethodVisualizer.dll and ILReader.dll to your "My Documents\Visual Studio 2005\Visualizers" folder (or follow &lt;A href="http://search.msn.com/results.aspx?q=msdn+how+to+install+visualizer" mce_href="http://search.msn.com/results.aspx?q=msdn+how+to+install+visualizer"&gt;this search result&lt;/A&gt;). &lt;/P&gt;
&lt;P&gt;Any comments are welcome. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Update&lt;/STRONG&gt; (December 30, 2005): As Toby and others pointed out below, there was some issue around branch instructions. I fixed it and updated the source code at gotdotnet site. Also&amp;nbsp;this version avoids using registry to&amp;nbsp;keep&amp;nbsp;the application settings.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Update&lt;/STRONG&gt; (December 1, 2006): New version can be found &lt;A class="" href="http://blogs.msdn.com/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=484861" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/484861.ashx" length="43370" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item></channel></rss>