<?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 : Reflection</title><link>http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx</link><description>Tags: Reflection</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>SignatureResolver (unfinished)</title><link>http://blogs.msdn.com/haibo_luo/archive/2008/03/08/8115220.aspx</link><pubDate>Sun, 09 Mar 2008 01:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8115220</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/8115220.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=8115220</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=8115220</wfw:comment><description>&lt;p&gt;While writing the ILVisualizer for dynamic method late 2005, I'd like to show the local variable information as well; so I started working on the managed signature parser, at least to parse LocalVarSig (Ecma-335 23.2.6). It was 2+ years ago, and never got to a finished state. Now perhaps I will never spend more time on it, so I refreshed the code a bit and you may find it useful for some scenarios.&lt;/p&gt;
&lt;p&gt;Here is an example of how to use SignatureResolver to get LocalVarSig in IronPython. The static method SignatureResolver.GetLocalVarSig takes the byte array (the signature blob) and the enclosing method, and returns an array of LocalVar (which includes mainly the runtime type) inside that method.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: green;"&gt;# show local variables for every Array.CreateInstance overload methods&lt;br&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;import &lt;/span&gt;clr&lt;br&gt;&lt;span style="color: blue;"&gt;import &lt;/span&gt;System&lt;br&gt;clr.AddReference(&lt;span style="color: maroon;"&gt;"ClrTest.Reflection.SignatureResolver"&lt;/span&gt;)&lt;br&gt;&lt;span style="color: blue;"&gt;from &lt;/span&gt;ClrTest.Reflection &lt;span style="color: blue;"&gt;import &lt;/span&gt;*&lt;br&gt;&lt;br&gt;&lt;span style="color: blue;"&gt;for &lt;/span&gt;method &lt;span style="color: blue;"&gt;in &lt;/span&gt;clr.GetClrType(System.Array).GetMember(&lt;span style="color: maroon;"&gt;"CreateInstance"&lt;/span&gt;):&lt;br&gt;    body = method.GetMethodBody()   &lt;span style="color: green;"&gt;# C# won't allow this&lt;br&gt;    &lt;/span&gt;tok = body.LocalSignatureMetadataToken&lt;br&gt;    sig = method.DeclaringType.Module.ResolveSignature(tok)&lt;br&gt;    &lt;span style="color: blue;"&gt;print &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;gt; %s, 0x%x" &lt;/span&gt;% (method, tok)&lt;br&gt;    &lt;span style="color: blue;"&gt;for &lt;/span&gt;lv &lt;span style="color: blue;"&gt;in &lt;/span&gt;SignatureResolver.GetLocalVarSig(sig, method):&lt;br&gt;        &lt;span style="color: blue;"&gt;print &lt;/span&gt;lv&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Next is part of the output showing one &lt;a href="http://msdn2.microsoft.com/en-us/library/x836773a.aspx" target="_blank" mce_href="http://msdn2.microsoft.com/en-us/library/x836773a.aspx"&gt;Array.CreateInstance&lt;/a&gt; method's local variable types. The result is, of course, same as what Reflector tells us in the below picture. "(p)" means the local variable is pinned.&lt;/p&gt;&lt;pre class="code"&gt;&amp;gt; System.Array CreateInstance(System.Type, Int32[], Int32[]), 0x11000009&lt;br&gt;System.RuntimeType &lt;br&gt;System.Int32 &lt;br&gt;System.Int32&amp;amp; (p)&lt;br&gt;System.Int32&amp;amp; (p)&lt;br&gt;System.Array &lt;br&gt;System.Int32[] &lt;br&gt;System.Int32[] &lt;br&gt;System.RuntimeTypeHandle &lt;br&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/ManagedSignatureResolverincomplete_DEB4/arraycreateinstanceloc.png" mce_href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/ManagedSignatureResolverincomplete_DEB4/arraycreateinstanceloc.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/ManagedSignatureResolverincomplete_DEB4/arraycreateinstanceloc_thumb.png" style="border-width: 0px;" alt="arraycreateinstanceloc" mce_src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/ManagedSignatureResolverincomplete_DEB4/arraycreateinstanceloc_thumb.png" border="0" height="233" width="823"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Yes, I understand the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.localvariables.aspx" target="_blank" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.localvariables.aspx"&gt;MethodBody.LocalVariables&lt;/a&gt; property gives us the similar information; but the dynamic method can not. That was why I wanted to decode the bytes, and to use DynamicScopeTokenResolver to get a meaningful type string. I admit this version of code diverts from its original goal: it only works for RuntimeMethodInfo/RuntimeConstructorInfo, and won't work for dynamic method; but if one day, you are in need of parsing blob, the functions like GetToken/GetInt32Uncompressed could be handy. GetToken basically is the reverse of TypeDefOrRefEncoded (ecma-335: 23.2.8)&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue;"&gt;int &lt;/span&gt;GetToken() {&lt;br&gt;    &lt;span style="color: blue;"&gt;int &lt;/span&gt;token = GetInt32Uncompressed();&lt;br&gt;    &lt;span style="color: blue;"&gt;return &lt;/span&gt;s_mapForTokenType[token &amp;amp; 0x03] | (token &amp;gt;&amp;gt; 2);&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;span style="color: blue;"&gt;int &lt;/span&gt;GetInt32Uncompressed() {&lt;br&gt;    &lt;span style="color: blue;"&gt;byte &lt;/span&gt;first = _sig[_pos];&lt;br&gt;&lt;br&gt;    &lt;span style="color: blue;"&gt;if &lt;/span&gt;(first &amp;lt;= 0x7F) {&lt;br&gt;        &lt;span style="color: blue;"&gt;return &lt;/span&gt;_sig[_pos++];&lt;br&gt;    } &lt;span style="color: blue;"&gt;else if &lt;/span&gt;(first &amp;lt;= 0xBF) {&lt;br&gt;        &lt;span style="color: blue;"&gt;byte&lt;/span&gt;[] bytes = &lt;span style="color: blue;"&gt;new byte&lt;/span&gt;[2];&lt;br&gt;        bytes[1] = (&lt;span style="color: blue;"&gt;byte&lt;/span&gt;)(_sig[_pos++] - 0x80);&lt;br&gt;        bytes[0] = _sig[_pos++];&lt;br&gt;        &lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;BitConverter&lt;/span&gt;.ToInt16(bytes, 0);&lt;br&gt;    } &lt;span style="color: blue;"&gt;else &lt;/span&gt;{&lt;br&gt;        &lt;span style="color: blue;"&gt;byte&lt;/span&gt;[] bytes = &lt;span style="color: blue;"&gt;new byte&lt;/span&gt;[4];&lt;br&gt;        bytes[3] = (&lt;span style="color: blue;"&gt;byte&lt;/span&gt;)(_sig[_pos++] - 0xC0);&lt;br&gt;        bytes[2] = _sig[_pos++];&lt;br&gt;        bytes[1] = _sig[_pos++]; ;&lt;br&gt;        bytes[0] = _sig[_pos++];&lt;br&gt;        &lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;BitConverter&lt;/span&gt;.ToInt32(bytes, 0);&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;My SignatureResolver also provide another static method GetMethodRefSig to get MethodRefSig (Ecma-335 22.25 and 23.2.2). &lt;/p&gt;
&lt;p&gt;If you are interested in this topic, you may download the attached file, unzip it, and take a look at the source. Also try to use VS2008 to build it. &lt;/p&gt;
&lt;p&gt;If you are an &lt;a href="http://www.codeplex.com/IronPython" mce_href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt; user, you may try the accompanying tests (in IronPython). I compare the SignatureResolver.GetLocalVarSig result with the official reflection API MethodBody.LocalVariables: they are same for all method/constructors from all simple-LoadFrom-successful framework assemblies. If you have ClrTest.Reflection.ILReader.dll (or know how to get one), you can try test_methodrefsig.py, which tests GetMethodRefSig. &lt;/p&gt;
&lt;p&gt;As stated in the title, this is *unfinished* and could be buggy. &lt;/p&gt;
&lt;p&gt;Disclaimer: THE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES INTENDED OR IMPLIED. USE AT YOUR OWN RISK.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8115220" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/8115220.ashx" length="7963" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><item><title>Name of Array Type</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/11/28/1169887.aspx</link><pubDate>Wed, 29 Nov 2006 09:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1169887</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/1169887.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=1169887</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=1169887</wfw:comment><description>&lt;P&gt;Two things related to array type name came to my mind while writing the previous post.&lt;/P&gt;
&lt;P&gt;Given an one-dimensional non-zero based double array x, x.GetType().ToString() returns "System.Double&lt;STRONG&gt;[*]&lt;/STRONG&gt;"; we can use Type.GetType("System.Double[*]") to get hold of such type easily. To get an instance of such type, instead of calling &lt;A href="http://msdn2.microsoft.com/en-us/library/x836773a.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/x836773a.aspx"&gt;Array.CreateInstance&lt;/A&gt;, we can find ConstructorInfo first, and call &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.constructorinfo.invoke.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.constructorinfo.invoke.aspx"&gt;ConstructorInfo.Invoke&lt;/A&gt;. Believe it or not, this type has 2 constructors, one is to create zero-based array, the other one for non-zero-based array.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt; t1 = &lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.GetType(&lt;SPAN class=csstring&gt;"System.Double[*]&lt;/SPAN&gt;");&lt;BR&gt;&lt;SPAN class=cstype&gt;ConstructorInfo&lt;/SPAN&gt;[] ctors = t1.GetConstructors();&lt;BR&gt;foreach (&lt;SPAN class=cstype&gt;ConstructorInfo&lt;/SPAN&gt; ci in ctors)&lt;BR&gt;&lt;SPAN class=cstype&gt;&amp;nbsp; &amp;nbsp; Console&lt;/SPAN&gt;.WriteLine(ci); &lt;SPAN class=cscomment&gt;// print "Void .ctor(Int32)" and "Void .ctor(Int32, Int32)"&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cstype&gt;Array&lt;/SPAN&gt; a1 = (&lt;SPAN class=cstype&gt;Array&lt;/SPAN&gt;)ctors[0].Invoke(&lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;object&lt;/SPAN&gt;[] { 10 });&lt;BR&gt;&lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.WriteLine(a1.GetType()); &lt;SPAN class=cscomment&gt;// print "System.Double[]"&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cstype&gt;Array&lt;/SPAN&gt; a2 = (&lt;SPAN class=cstype&gt;Array&lt;/SPAN&gt;)ctors[1].Invoke(&lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;object&lt;/SPAN&gt;[] { -5, 10 }); &lt;SPAN class=cscomment&gt;// lowerbound: -5 &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.WriteLine(a2.GetType()); &lt;SPAN class=cscomment&gt;// print "System.Double[*]"&lt;/SPAN&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Type.GetType("System.Int32&lt;STRONG&gt;[,][]&lt;/STRONG&gt;") returns a jagged array, more precisely, a one-dimensional array whose elements are two-dimensional arrays, This is different from the type "int[,][]" declared in C#, which is a two-dimensional array of one-dimensional arrays. The type name grammar used in Type.GetType is more close to how IL describes such array: you can see a3's type as "int32[0...,0...][]" in ildasm.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt; t2 = &lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.GetType(&lt;SPAN class=csstring&gt;"System.Int32[,][]&lt;/SPAN&gt;");&lt;BR&gt;&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;[][,] a3 = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;[2][,] { &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;[,] { { 1, 2 } }, &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;[,] { { 3, 4, 5 }, { 6, 7, 8 } } };&lt;BR&gt;&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;[,][] a4 = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;[1, 2][] { { &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;[] { 1, 2 }, &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;[] { 3, 4, 5 } } };&lt;BR&gt;&lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.WriteLine(a3.GetType() == t2); &lt;SPAN class=cscomment&gt;// True&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.WriteLine(a4.GetType() == t2); &lt;SPAN class=cscomment&gt;// False&lt;/SPAN&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;DIV class=ilcode&gt;.locals init (&lt;BR&gt;&amp;nbsp;&amp;nbsp; [6] int32[0...,0...][] a3,&amp;nbsp;&lt;BR&gt;&amp;nbsp; &amp;nbsp;[7] int32[][0...,0...] a4, &lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1169887" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><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>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>Member Order Returned by GetFields, GetMethods ...</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/07/09/661091.aspx</link><pubDate>Mon, 10 Jul 2006 09:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:661091</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/661091.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=661091</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=661091</wfw:comment><description>	&lt;p&gt;
		As John mentioned in his &lt;a href="http://devauthority.com/blogs/johnwood/archive/2005/06/29/79.aspx"&gt;
			post&lt;/a&gt;, every Reflection user should keep this in mind: our code should not
		count on the member order returned by GetFields, GetMethods and other similar GetXXXs
		calls.&lt;/p&gt;
	&lt;p&gt;
		Given two fields (F1, F2) in one type, I think the compiler is free to emit F1 before
		F2, or vice versa. Also reflection does not guarantee to return fields in the order
		of how they present in the metadata; GetXXXs could be returning the members in different
		order at different running moments, which is illustrated by the following code.
		(Of course, they should have the same set of members)
	&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;br /&gt;
		&lt;span class="cskeyword"&gt;public class&lt;/span&gt; &lt;span class="cstype"&gt;C&lt;/span&gt; {&lt;br /&gt;
		&amp;nbsp; &lt;span class="cskeyword"&gt;public int&lt;/span&gt; F1;&lt;br /&gt;
		&amp;nbsp; &lt;span class="cskeyword"&gt;public int&lt;/span&gt; F2;&lt;br /&gt;
		&lt;br /&gt;
		&amp;nbsp; &lt;span class="cskeyword"&gt;static void&lt;/span&gt; Main() {&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;C&lt;/span&gt;).GetField(&lt;span
			class="csstring"&gt;"F2"&lt;/span&gt;); &lt;span class="cscomment"&gt;// Line 9&lt;/span&gt;&lt;br /&gt;
		&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; PrintFields(); &lt;span class="cscomment"&gt;// Line 11&lt;/span&gt;&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; PrintFields(); &lt;span class="cscomment"&gt;// Line 12&lt;/span&gt;&lt;br /&gt;
		&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;GC&lt;/span&gt;.Collect();&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;GC&lt;/span&gt;.WaitForPendingFinalizers(); &lt;span class="cscomment"&gt;
			// Line 15&lt;/span&gt;&lt;br /&gt;
		&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; PrintFields(); &lt;span class="cscomment"&gt;// Line 17&lt;/span&gt;&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; PrintFields(); &lt;span class="cscomment"&gt;// Line 18&lt;/span&gt;&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		&amp;nbsp; &lt;span class="cskeyword"&gt;static void&lt;/span&gt; PrintFields() {&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;foreach&lt;/span&gt; (&lt;span class="cstype"&gt;FieldInfo&lt;/span&gt;
		fi &lt;span class="cskeyword"&gt;in typeof&lt;/span&gt;(&lt;span class="cstype"&gt;C&lt;/span&gt;).GetFields())&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.Write(&lt;span class="csstring"&gt;"{0}
			"&lt;/span&gt;, fi.Name);&lt;br /&gt;
		&amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine();&lt;br /&gt;
		&amp;nbsp; }&lt;br /&gt;
		}&lt;br /&gt;
	&lt;/div&gt;
	&lt;p&gt;
		Below is mostly like what you will get when running under .NET 2.0 (50727.42). You
		may download the attached C# file, and get it a try. (By the way, the PE file generated
		by C# compiler has F1 before F2 in the metadata).&lt;/p&gt;
	&lt;div class="csharp"&gt;
		&amp;gt; &lt;span class="typein"&gt;FieldOrder.exe&lt;/span&gt;&lt;br /&gt;
		F1 F2&lt;br /&gt;
		F2 F1&lt;br /&gt;
		F1 F2&lt;br /&gt;
		F1 F2&lt;br /&gt;
	&lt;/div&gt;
	&lt;p&gt;
		Behind the scenes is reflection 2.0's MemberInfo caching mechanism. &lt;a href="http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/"&gt;
			Joel Pobar’s MSDN article&lt;/a&gt; has a nice overview about it. Here are some basic
		facts before diving into each important line.&lt;/p&gt;
	&lt;ol&gt;
		&lt;li&gt;Each type has its own MemberInfo caches. Reflection creates different caches for
			different member types, one for each (if necessary): FieldInfo, MethodInfo, ConstructorInfo...&lt;/li&gt;
		&lt;li&gt;The caches are created and populated lazily. If ConstructorInfos are never asked,
			the ConstructorInfo cache will not be created. If only one method is requested for
			MethodInfo, only that method’s MethodInfo will be populated into the MethodInfo
			cache, not with all other methods.&lt;/li&gt;
		&lt;li&gt;The type keeps a weak reference to its MemberInfo caches, so, for example, when
			there is no reference to this type’s FieldInfos, the runtime could reclaim the memory
			used by the FieldInfo cache.&lt;/li&gt;
	&lt;/ol&gt;
	&lt;p&gt;
		&lt;strong&gt;Line 9&lt;/strong&gt;: we are asking for FieldInfo of "F2". At that time, the
		type C’s FieldInfo cache is null, Reflection will create the cache, look for the
		field with name "F2", create an object RuntimeFieldInfo, and put it into the cache.
		Imagining the cache looks like an ArrayList, the first element of the cache now
		contains FieldInfo "F2".&lt;/p&gt;
	&lt;img src="http://static.flickr.com/71/186195592_4bc6412976_o.gif" alt="fieldInfo cache change"
		style="float: right" /&gt;
	&lt;p&gt;
		&lt;strong&gt;Line 11&lt;/strong&gt;: typeof(C).GetFields() asks for type C's all fields (with
		default binding flags). It goes through all fields, and returns an array of FieldInfo
		(in order of F1/F2). Before returning this array back to the user, it updates the
		cache: appending "F1" after "F2" ("F2" already exists as the result of line 9).
		It also marks this cache "complete".&lt;/p&gt;
	&lt;p&gt;
		&lt;strong&gt;Line 12&lt;/strong&gt;: the 2nd GetFields notices that the cache was built completely,
		immediately scans the cache, and returns an array of FieldInfo F2/F1 in that order.&lt;/p&gt;
	&lt;p&gt;
		&lt;strong&gt;Line 17&lt;/strong&gt;: the 3rd GetFields occurs after GC, where the FieldInfo
		cache was reclaimed; GetFields has to re-create the cache. It goes through all fields
		again, and the cache is filled with FieldInfos in the order of F1/F2.&lt;/p&gt;
	&lt;p&gt;
		&lt;strong&gt;Line 18&lt;/strong&gt;: same reason as the 2nd GetFields call, it returns F1/F2
		quickly.&lt;/p&gt;
	&lt;p&gt;
		The picture at right shows the appearance/changes of the FieldInfo cache. Note the
		cache after line 11 has F2 in front of F1, GetFields at that line still returns
		F1/F2.
	&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=661091" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/661091.ashx" length="566" type="text/plain" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><item><title>My Attribute Disappears</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/02/21/536470.aspx</link><pubDate>Wed, 22 Feb 2006 02:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:536470</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/536470.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=536470</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=536470</wfw:comment><description>    &lt;p&gt;
        The GetCustomAttributes scenario (&lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.icustomattributeprovider.getcustomattributes.aspx"&gt;ICustomAttributeProvider.GetCustomAttributes&lt;/a&gt;
        or &lt;a href="http://msdn2.microsoft.com/en-us/library/system.attribute.getcustomattributes.aspx"&gt;
            Attribute.GetCustomAttributes&lt;/a&gt;, referred to as GetCA in this post) involves
        3 pieces:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;a custom attribute type&lt;/li&gt;&lt;li&gt;an entity which is decorated with the custom attribute&lt;/li&gt;
        &lt;li&gt;a code snippet calling GetCA on the decorated entity.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;
        These pieces could be residing together in one assembly; or separately in 3 different
        assemblies. The following C# code shows each piece in separate files, and I will
        compile them into 3 assemblies: the attribute type assembly (attribute.dll), the
        decorated entity assembly (decorated.dll) and the querying assembly (getca.exe):&lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cscomment"&gt;// file: attribute.cs&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
        &lt;span class="cskeyword"&gt;public class &lt;/span&gt;&lt;span class="cstype"&gt;MyAttribute &lt;/span&gt;
        : System.&lt;span class="cstype"&gt;Attribute &lt;/span&gt;{ }
    &lt;/div&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cscomment"&gt;// file: decorated.cs&lt;/span&gt;&lt;br /&gt;
        [My]&lt;br /&gt;
        &lt;span class="cskeyword"&gt;public class&lt;/span&gt; &lt;span class="cstype"&gt;MyClass &lt;/span&gt;
        { }
    &lt;/div&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cscomment"&gt;// file: getca.cs &lt;/span&gt;
        &lt;br /&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;class &lt;/span&gt;Demo {
        &lt;br /&gt;
        &amp;nbsp; &lt;span class="cskeyword"&gt;static void &lt;/span&gt;Main(&lt;span class="cskeyword"&gt;string&lt;/span&gt;[]
        args) {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Assembly &lt;/span&gt;asm = &lt;span class="cstype"&gt;Assembly&lt;/span&gt;.LoadFrom(args[0]);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;object&lt;/span&gt;[] attrs = asm.GetType(&lt;span class="csstring"&gt;"MyClass"&lt;/span&gt;).GetCustomAttributes(&lt;span
            class="cskeyword"&gt;true&lt;/span&gt;);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(attrs.Length);&lt;br /&gt;
        &amp;nbsp; }&lt;br /&gt;
        }
    &lt;/div&gt;
    &lt;div class="csharp"&gt;
        D:\&amp;gt; &lt;span class="typein"&gt;sn.exe -k sn.key&lt;/span&gt;&lt;br /&gt;
        D:\&amp;gt; &lt;span class="typein"&gt;csc /t:library /keyfile:sn.key attribute.cs&lt;/span&gt;&lt;br /&gt;
        D:\&amp;gt; &lt;span class="typein"&gt;csc /t:library /r:attribute.dll decorated.cs&lt;/span&gt;&lt;br /&gt;
        D:\&amp;gt; &lt;span class="typein"&gt;gacutil -i attribute.dll&lt;br /&gt;
        &lt;/span&gt;D:\&amp;gt; &lt;span class="typein"&gt;del attribute.dll&lt;/span&gt;&lt;br /&gt;
        D:\&amp;gt; &lt;span class="typein"&gt;csc getca.cs&lt;/span&gt;
        &lt;br /&gt;
        D:\&amp;gt; &lt;span class="typein"&gt;getca.exe decorated.dll&lt;/span&gt;&lt;br /&gt;
        1&lt;br /&gt;
        D:\&amp;gt; &lt;span class="typein"&gt;getca.exe \\machine\d$\decorated.dll&lt;/span&gt;&lt;br /&gt;
        0
    &lt;/div&gt;
    &lt;p&gt;
        attribute.dll is installed in GAC (no local copy, to avoid confusion); getca.exe
        checks whether the loaded type MyClass has MyAttribute. As you see from the output,
        MyAttribute disappeared when the decorated entity was loaded from a share (or as
        a partially trusted assembly, to be precise).
    &lt;/p&gt;
    &lt;p&gt;
        GetCA is supposed to return an array of attribute objects. In order to do so, it
        parses the custom attribute metadata, finds the right custom attribute constructor,
        and then invokes that .ctor with some parameters (if any). It is a late-bound call,
        reflection decides whether the querying assembly should invoke the attribute .ctor,
        or avoid calling it for security reasons.
    &lt;/p&gt;
    &lt;p&gt;
        Let me quote something from &lt;a HREF="/shawnfa/archive/2005/02/04/367390.aspx"&gt;
            ShawnFa&lt;/a&gt;'s security blog: "by default, strongly named, fully trusted assemblies
        are given an implicit LinkDemand for FullTrust on every public and protected method
        of every publicly visible class". This means, in a scenario where a library is strongly
        named and fully trusted, partial trusted assemblies are unable to call into such
        library.
    &lt;/p&gt;
    &lt;p&gt;
        The GetCA scenario is not exactly the same, but similar. The .ctor to be invoked
        is in attribute.dll (in GAC, strongly named and fully trusted). The querying assembly
        (runs locally, fully trusted too) is the code that makes the invocation (if that
        were to happen). But to make this .ctor invocation, we need pass in the parameters,
        which are provided by the decorated entity assembly. &lt;em&gt;GetCA will take the decorated
            entity as the caller to the attribute type constructor&lt;/em&gt;. Based on what I
        just quoted, if the decorated entity assembly is partially trusted, we will filter
        out such attribute object creation, unless the attribute assembly is decorated with
        &lt;a href="http://msdn2.microsoft.com/en-us/library/system.security.allowpartiallytrustedcallersattribute.aspx"&gt;
            AllowPartiallyTrustedCallersAttribute&lt;/a&gt;. Note please read &lt;a HREF="/shawnfa/archive/2005/02/04/367390.aspx"&gt;
                Shawn's blog entry&lt;/a&gt; carefully about this attribute and its' security
        implications before taking this approach.&lt;/p&gt;
    &lt;p&gt;
        What if the attribute and decorated entity are in the same assembly? In this case,
        it does not matter whether the assembly is loaded from a share or locally. GetCA
        will try to create and return the attribute object. If the loaded assembly is partially
        trusted, the runtime gives it a smaller set of permissions and running the .ctor
        code is not going to do something terrible.&lt;/p&gt;
    &lt;p&gt;
        To close, GetCA will try to create the custom attribute object if any of the following
        3 conditions is true:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;the decorated entity and the custom attribute type are in one assembly, &lt;/li&gt;
        &lt;li&gt;the decorated entity is fully trusted,&lt;/li&gt;
        &lt;li&gt;the assembly which defines the custom attribute type is decorated with APTCA.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;
        By the way, the new class &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.customattributedata.aspx"&gt;
            CustomAttributeData&lt;/a&gt; in .NET 2.0 is designed to access custom attribute in
        the reflection-only context, where no code will be executed (only metadata checking).
        If we use CustomAttributeData.GetCustomAttributes instead in the above example,
        it prints 1; one CustomAttributeData object, not one MyAttribute object.&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=536470" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><item><title>Type.FullName returns null when ...</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/02/17/534480.aspx</link><pubDate>Sat, 18 Feb 2006 02:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:534480</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/534480.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=534480</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=534480</wfw:comment><description>    &lt;p&gt;
        &lt;a href="http://msdn2.microsoft.com/en-us/library/system.type.fullname.aspx"&gt;Type.FullName&lt;/a&gt;
        returns null when the type is not generic type definition but contains generic paramters.
    &lt;/p&gt;
    &lt;p&gt;
        The rational behind this design is to ensure Type.FullName (if not null) can uniquely
        identify a type in an assembly; or given the string returned by Type.FullName, &lt;a
            href="http://msdn2.microsoft.com/en-us/library/system.type.gettype.aspx"&gt;Type.GetType&lt;/a&gt;(string
        typeName) can return the original type back. It is hard to keep this invariant if
        &lt;br /&gt;
        &lt;span class="inlinecode"&gt;!type.IsGenericTypeDefinition &amp;amp;&amp;amp; type.ContainsGenericParameters&lt;/span&gt;.&lt;/p&gt;
    &lt;p&gt;
        For instance, suppose we have an assembly compiled with the following C# code:
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;class &lt;/span&gt;&lt;span class="cstype"&gt;G&lt;/span&gt;&amp;lt;T&amp;gt; {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M&amp;lt;S&amp;gt;() { }
        &lt;br /&gt;
        }&lt;/div&gt;
    &lt;p&gt;
        typeof(G&amp;lt;&amp;gt;).FullName is "G`1", and we can round trip this type from Type.GetType("G`1").
        But we can build more complicated generic types, such as G&amp;lt;S&amp;gt; (type G&amp;lt;&amp;gt;
        bound with the generic parameter from the method M&amp;lt;&amp;gt;); in order to identify
        such type with a string, a lot of extra information is need.
    &lt;/p&gt;
    &lt;p&gt;
        Below are some examples where Type.FullName returns null.
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;class &lt;/span&gt;&lt;span class="cstype"&gt;G&lt;/span&gt;&amp;lt;T&amp;gt; {&lt;br /&gt;
        &amp;nbsp; &lt;span class="cskeyword"&gt;public class &lt;/span&gt;&lt;span class="cstype"&gt;C&lt;/span&gt;
        { }&lt;br /&gt;
        &amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M(&lt;span class="cstype"&gt;C&lt;/span&gt;
        arg) { }&lt;br /&gt;
        }&lt;br /&gt;
        &lt;span class="cskeyword"&gt;class &lt;/span&gt;&lt;span class="cstype"&gt;G2&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span
            class="cstype"&gt;G&lt;/span&gt;&amp;lt;T&amp;gt; { }&lt;br /&gt;
        &lt;br /&gt;
        &lt;span class="cskeyword"&gt;string &lt;/span&gt;s1 = &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span
            class="cstype"&gt;G&lt;/span&gt;&amp;lt;&amp;gt;).GetGenericArguments()[0].FullName;
        &lt;br /&gt;
        &lt;span class="cscomment"&gt;// T in G&amp;lt;T&amp;gt;: generic parameter&lt;/span&gt;&lt;br class="cscomment" /&gt;
        &lt;span class="cskeyword"&gt;string &lt;/span&gt;s2 = &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span
            class="cstype"&gt;G&lt;/span&gt;&amp;lt;&amp;gt;).GetMethod(&lt;span class="csstring"&gt;"M"&lt;/span&gt;).GetParameters()[0].ParameterType.FullName;
        &lt;br /&gt;
        &lt;span class="cscomment"&gt;// check out the IL, it is G`1/C&amp;lt;!T&amp;gt; (not generic type
            definition)&amp;nbsp;&lt;br /&gt;
            // Related topic, see &lt;a HREF="/haibo_luo/archive/2005/09/28/474970.aspx"&gt;
                this&lt;/a&gt; &lt;/span&gt;
        &lt;br /&gt;
        &lt;span class="cskeyword"&gt;string &lt;/span&gt;s3 = &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span
            class="cstype"&gt;G2&lt;/span&gt;&amp;lt;&amp;gt;).BaseType.FullName;
        &lt;br /&gt;
        &lt;span class="cscomment"&gt;// base type of G2&amp;lt;&amp;gt;, which is not generic type definition
            either&lt;br /&gt;
            // it equals to typeof(G&amp;lt;&amp;gt;).MakeGenericType(typeof(G2&amp;lt;&amp;gt;).GetGenericArguments()[0])&lt;/span&gt;&lt;/div&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=534480" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><item><title>Use IronPython to Experiment .NET Libraries</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/01/18/Use-IronPython-to-Experiment-.NET-Libraries.aspx</link><pubDate>Thu, 19 Jan 2006 02:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:514601</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/514601.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=514601</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=514601</wfw:comment><description>&lt;p&gt;When working on .NET projects, we often need to find the right API or the proper parameters to pass in to a particular method. Usually we search MSDN or turn to other search engines to solve such issue. Some people, however, prefer first-hand experience over search; they perfer experimenting or playing with a small piece of C# or VB.Net code. These people probably should consider using &lt;a href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=ad7acff7-ab1e-4bcb-99c0-57ac5a3a9742" mce_href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=ad7acff7-ab1e-4bcb-99c0-57ac5a3a9742"&gt;IronPython&lt;/a&gt;, which I found can save a lot of edit-save-compile-run cycles.&lt;/p&gt;
&lt;p&gt;For example, suppose I want to make sure I understand the functionality of Path.GetTempFileName and Path.GetRandomName before using either API in my code. This is how I would do in IronPython:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;D:\IronPython &amp;gt; &lt;b&gt;IronPythonConsole.exe&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;import System&lt;br&gt;&lt;/b&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;from System.IO import *&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;Path.GetTempFileName()&lt;/b&gt;&lt;br&gt;'C:\\Documents and Settings\\username\\Local Settings\\Temp\\tmpEE7.tmp'&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;Path.GetRandomFileName()&lt;/b&gt;&lt;br&gt;'fbrhamew.f13'&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We see the instant functionality result with 4 lines of python code. No Ctrl+S, No csc.exe or vbc.exe... Another example: the tricky method String.Format(string, object). Sometimes we need to tweak the formatting string, rebuild the entire solution several times to get the expected string. Let us try to format a long number to 8-char hex. After trying a few different things based on my vague memory, finally I get what I want. &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;from System import *&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;String.Format("{0,8:X}", 12345678)&lt;/b&gt;&lt;br&gt;' BC614E'&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;String.Format("{0,X8}", 12345678)&lt;/b&gt;&lt;br&gt;Traceback (most recent call last):&lt;br&gt;File , line 0, in input##37&lt;br&gt;File , line 0, in Format&lt;br&gt;File , line 0, in AppendFormat&lt;br&gt;File , line 0, in FormatError&lt;br&gt;SystemError: Input string was not in a correct format.&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;String.Format("{0:X8}", 12345678)&lt;/b&gt;&lt;br&gt;'00BC614E'&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Don't like typing? IronPythonConsole keeps the history, so we can use up/down key to get our previous codes back, and then do a little more editing. Or we can save the method object first, and easily have &lt;a href="http://blogs.msdn.com/brada/archive/2004/01/14/58851.aspx" mce_href="http://blogs.msdn.com/brada/archive/2004/01/14/58851.aspx"&gt;more String.Format fun&lt;/a&gt; (yeah...next time you want to play with code snippets when reading blogs, try doing so with IronPython...)&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;f = String.Format&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;f("{0:X8}", 12345678&lt;/b&gt;)&lt;br&gt;'00BC614E'&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;f("{{0:X8}}", 12345678)&lt;/b&gt;&lt;br&gt;'{0:X8}'&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;f("{{{0:X8}}}", 12345678)&lt;/b&gt;&lt;br&gt;'{X8}'&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Just another FYI: 1.0 Beta1 also shipped a winform version console: IronPythonWindowConsole.exe, which provides similar typing experience like VS IDE intellisense.&lt;/p&gt;
&lt;p&gt;Let me finish this post with an experiment with &lt;a href="http://msdn2.microsoft.com/en-us/library/System.Reflection.BindingFlags.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/System.Reflection.BindingFlags.aspx"&gt;System.Reflection.BindingFlags&lt;/a&gt; (seems this is really confusing). I will try with the type of &lt;a href="http://msdn2.microsoft.com/en-us/library/System.Random.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/System.Random.aspx"&gt;System.Random&lt;/a&gt;; Reflector shows this type as follows (I will only focus on these 8 methods):&lt;/p&gt;&lt;pre&gt;[Serializable, ComVisible(true)]&lt;br&gt;public class Random&lt;br&gt;{&lt;br&gt;      // Methods&lt;br&gt;      public Random();&lt;br&gt;      public Random(int Seed);&lt;br&gt;      private double GetSampleForLargeRange();&lt;br&gt;      private int InternalSample();&lt;br&gt;      public virtual int Next();&lt;br&gt;      public virtual int Next(int maxValue);&lt;br&gt;      public virtual int Next(int minValue, int maxValue);&lt;br&gt;      public virtual void NextBytes(byte[] buffer);&lt;br&gt;      public virtual double NextDouble();&lt;br&gt;      protected virtual double Sample();&lt;br&gt;&lt;br&gt;      // Fields&lt;br&gt;      ......&lt;br&gt;} &lt;br&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;import System&lt;br&gt;&lt;/b&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;from System import *&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;from System.Reflection import *&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;r = Random(&lt;/b&gt;)&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;t = r.GetType()&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;gm = t.GetMethods&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;gm()&lt;/b&gt;&lt;br&gt;System.Reflection.MethodInfo[](Int32 Next(), Int32 Next(Int32, Int32), Int32 Next(Int32), Double NextDouble(), Void NextBytes(Byte[]), System.Type GetType(), System.String ToString(), Boolean Equals(System.Object), Int32 GetHashCode())&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;_.Length&lt;/b&gt;&lt;br&gt;9&lt;br&gt;&lt;/span&gt;&lt;span&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; It also includes 4 public methods defined in System.Object; and no private/protected methods&lt;/i&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;bf = BindingFlags&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;gm(bf.Public)&lt;/b&gt;&lt;br&gt;System.Reflection.MethodInfo[]()&lt;br&gt;&lt;/span&gt;&lt;span&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Nothing returned if only specifying Public, need another flag?&lt;/i&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;gm(bf.Public | bf.Static)&lt;/b&gt;&lt;br&gt;System.Reflection.MethodInfo[]()&lt;br&gt;&lt;/span&gt;&lt;span&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; This ca&lt;/i&gt;&lt;i&gt;n not tell much, since Random does not have static methods.&lt;/i&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;gm(bf.Public | bf.Instance)&lt;/b&gt;&lt;br&gt;System.Reflection.MethodInfo[](Int32 Next(), Int32 Next(Int32, Int32), Int32 Next(Int32), Double NextDouble(), Void NextBytes(Byte[]), System.Type GetType(), System.String ToString(), Boolean Equals(System.Object), Int32 GetHashCode())&lt;br&gt;&lt;/span&gt;&lt;span&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Looks same as gm() returned? Actually gm() returns static methods too, but for this example, Random does not have any.&lt;/i&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;gm(bf.Public | bf.Instance | bf.DeclaredOnly)&lt;/b&gt;&lt;br&gt;System.Reflection.MethodInfo[](Int32 Next(), Int32 Next(Int32, Int32), Int32 Next(Int32), Double NextDouble(), Void NextBytes(Byte[]))&lt;br&gt;&lt;/span&gt;&lt;span&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DeclaredOnly will not return the 4 methods defined in System.Object&lt;/i&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;gm(bf.NonPublic | bf.Instance)&lt;/b&gt;&lt;br&gt;System.Reflection.MethodInfo[](Double Sample(), Int32 InternalSample(), Double GetSampleForLargeRange(), System.Object MemberwiseClone(), Void Finalize())&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;_.Length&lt;/b&gt;&lt;br&gt;5&lt;br&gt;&lt;/span&gt;&lt;span&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Get back protected method Sample() here, and another 2 private methods defined in Sample; also 2 methods from System.Object &lt;/i&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: x-small; font-family: 'Courier New';"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;gm(bf.Public | bf.NonPublic | bf.Instance)&lt;/b&gt;&lt;br&gt;System.Reflection.MethodInfo[](Double Sample(), Int32 InternalSample(), Int32 Next(), Double GetSampleForLargeRange(), Int32 Next(Int32, Int32), Int32 Next(Int32), Double NextDouble(), Void NextBytes(Byte[]), System.Type GetType(), System.Object MemberwiseClone(), System.String ToString(), Boolean Equals(System.Object), Int32 GetHashCode(), Void Finalize())&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;_.Length&lt;/b&gt;&lt;br&gt;14&lt;br&gt;&lt;/span&gt;&lt;span&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; We got back all 14(5+9) instance methods from type Object and Random, public, protected or private&lt;/i&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ...&lt;/span&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=514601" 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/IronPython/default.aspx">IronPython</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>Read IL from MethodBody</title><link>http://blogs.msdn.com/haibo_luo/archive/2005/10/04/476242.aspx</link><pubDate>Tue, 04 Oct 2005 21:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:476242</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/476242.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=476242</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=476242</wfw:comment><description>    &lt;p&gt;
        Reflection in .NET 2.0 ships with a new class MethodBody, which "provides access
        to information about the local variables and exception-handling clauses in a method
        body, and to the Microsoft intermediate language (MSIL) that makes up the method
        body". (Thanks to Glenn, who wrote &lt;a href="http://msdn2.microsoft.com/library/28ec3e6z(en-us,vs.80).aspx"&gt;
            this&lt;/a&gt; in the MSDN doc; I simply copy &amp;amp; paste it). The only one method
        inside this class (others are properties) is:
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;public byte&lt;/span&gt;[] GetILAsByteArray()
    &lt;/div&gt;
    &lt;p&gt;
        which returns us a byte array containing IL content for this method body.
    &lt;/p&gt;
    &lt;p&gt;
        Recently we got some questions related to reflecting IL stream: users want to check
        where a specific method was used; or try to build a call graph inside an assembly;...
        Reflection currently does not support this directly. Lutz Roeder's awesome tool
        - &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;.NET Reflector&lt;/a&gt; can indeed show
        the call/callee graph for each method. I used to have the source code for his ILReader,
        and noticed it did not use Reflection APIs (so for sure we can read IL without reflection
        APIs)
    &lt;/p&gt;
    &lt;p&gt;
        A code sketch below shows how we can use classes in the Reflection/Emit namespace
        (and other useful APIs provided in .NET 2.0) to read IL instructions. &lt;a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm"&gt;
            Standard ECMA-335&lt;/a&gt; is the authoritative resource to understand IL, MethodBody
        format and other CLI topics if you want to know more of them.
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;public class&lt;/span&gt; &lt;span class="cstype"&gt;ILReader &lt;/span&gt;
        : &lt;span class="cstype"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span class="cstype"&gt;ILInstruction&lt;/span&gt;&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Byte&lt;/span&gt;[] m_byteArray;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Int32 &lt;/span&gt;m_position;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;MethodBase &lt;/span&gt;m_enclosingMethod;&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;static &lt;/span&gt;&lt;span class="cstype"&gt;OpCode&lt;/span&gt;[]
        s_OneByteOpCodes = &lt;span class="cskeyword"&gt;new &lt;/span&gt;&lt;span class="cstype"&gt;OpCode&lt;/span&gt;[0x100];&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;static &lt;/span&gt;&lt;span class="cstype"&gt;OpCode&lt;/span&gt;[]
        s_TwoByteOpCodes = &lt;span class="cskeyword"&gt;new &lt;/span&gt;&lt;span class="cstype"&gt;OpCode&lt;/span&gt;[0x100];&amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;static &lt;/span&gt;ILReader()&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;foreach &lt;/span&gt;(&lt;span class="cstype"&gt;FieldInfo
        &lt;/span&gt;fi in &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;OpCodes&lt;/span&gt;).GetFields(&lt;span
            class="cstype"&gt;BindingFlags&lt;/span&gt;.Public | &lt;span class="cscomment"&gt;BindingFlags&lt;/span&gt;.Static))&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;OpCode &lt;/span&gt;opCode = (&lt;span class="cstype"&gt;OpCode&lt;/span&gt;)fi.GetValue(&lt;span
            class="cskeyword"&gt;null&lt;/span&gt;);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;UInt16 &lt;/span&gt;value = (&lt;span class="cstype"&gt;UInt16&lt;/span&gt;)opCode.Value;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="cskeyword"&gt;if &lt;/span&gt;(value &amp;lt; 0x100)&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; s_OneByteOpCodes[value] = opCode;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;else if &lt;/span&gt;((value &amp;amp;
        0xff00) == 0xfe00)&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; s_TwoByteOpCodes[value &amp;amp; 0xff] = opCode;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; }&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public &lt;/span&gt;ILReader(&lt;span class="cstype"&gt;MethodBase
        &lt;/span&gt;enclosingMethod)&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;this&lt;/span&gt;.m_enclosingMethod = enclosingMethod;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;MethodBody &lt;/span&gt;methodBody = m_enclosingMethod.GetMethodBody();&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;this&lt;/span&gt;.m_byteArray = (methodBody
        == &lt;span class="cskeyword"&gt;null&lt;/span&gt;) ? &lt;span class="cskeyword"&gt;new &lt;/span&gt;&lt;span
            class="cstype"&gt;Byte&lt;/span&gt;[0] : methodBody.&lt;b&gt;GetILAsByteArray&lt;/b&gt;();&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;this&lt;/span&gt;.m_position = 0;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public IEnumerator&lt;/span&gt;&amp;lt;&lt;span class="cskeyword"&gt;ILInstruction&lt;/span&gt;&amp;gt;GetEnumerator()&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;while &lt;/span&gt;(m_position &amp;lt; m_byteArray.Length)&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;yield return &lt;/span&gt;Next();&lt;br /&gt;
        &lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; m_position = 0;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;yield break&lt;/span&gt;;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; }&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; System.Collections.&lt;span class="cstype"&gt;IEnumerator &lt;/span&gt;System.Collections.&lt;span
            class="cstype"&gt;IEnumerable&lt;/span&gt;.GetEnumerator()&amp;nbsp; { &lt;span class="cskeyword"&gt;return
                this.&lt;/span&gt;GetEnumerator(); }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;ILInstruction &lt;/span&gt;Next()&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Int32 &lt;/span&gt;offset = m_position;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;OpCode &lt;/span&gt;opCode = &lt;span class="cstype"&gt;
            OpCodes&lt;/span&gt;.Nop;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Int32 &lt;/span&gt;token = 0;&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;// read first 1 or 2 bytes as opCode&lt;/span&gt;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Byte &lt;/span&gt;code = ReadByte();&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;if &lt;/span&gt;(code != 0xFE)&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; opCode = s_OneByteOpCodes[code];&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;else&lt;/span&gt;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; code = ReadByte();&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; opCode = s_TwoByteOpCodes[code];&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;switch &lt;/span&gt;(opCode.OperandType)&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; {&lt;br /&gt;
        &lt;span id="Span1"&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;
        &lt;span class="cstype"&gt;&lt;span class="cstype"&gt;OperandType&lt;/span&gt;&lt;/span&gt;.InlineNone:&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;return new&lt;/span&gt; InlineNoneInstruction(m_enclosingMethod,
        offset, opCode);&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;&lt;span class="cskeyword"&gt;case &lt;/span&gt;
        &lt;/span&gt;&lt;span class="cstype"&gt;OperandType&lt;/span&gt;.ShortInlineBrTarget:&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;SByte &lt;/span&gt;shortDelta =
        ReadSByte();&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;return new&lt;/span&gt; ShortInlineBrTargetInstruction(m_enclosingMethod,
        offset, opCode, shortDelta);&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;&lt;span class="cskeyword"&gt;case &lt;/span&gt;
        &lt;/span&gt;&lt;span class="cstype"&gt;OperandType&lt;/span&gt;.InlineBrTarget: &lt;span class="cstype"&gt;
            Int32 &lt;/span&gt;delta = ReadInt32(); &amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;&lt;span class="cskeyword"&gt;
                return new&lt;/span&gt;&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;&lt;span class="cskeyword"&gt;case &lt;/span&gt;
        &lt;/span&gt;&lt;span class="cstype"&gt;OperandType&lt;/span&gt;.ShortInlineI: &amp;nbsp; &lt;span class="cstype"&gt;
            Byte &lt;/span&gt;int8 = ReadByte(); &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;return
                new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;&lt;span class="cskeyword"&gt;case &lt;/span&gt;
        &lt;/span&gt;&lt;span class="cstype"&gt;OperandType&lt;/span&gt;.InlineI: &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;
        &lt;span class="cstype"&gt;Int32 &lt;/span&gt;int32 = ReadInt32(); &amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;
            return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineI8: &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Int64 &lt;/span&gt;
        int64 = ReadInt64(); &amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.ShortInlineR: &amp;nbsp; &lt;span class="cstype"&gt;Single &lt;/span&gt;float32
        = ReadSingle(); &lt;span class="cskeyword"&gt;return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineR: &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Double &lt;/span&gt;
        float64 = ReadDouble(); &lt;span class="cskeyword"&gt;return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.ShortInlineVar: &lt;span class="cstype"&gt;Byte &lt;/span&gt;index8 =
        ReadByte(); &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineVar: &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;UInt16 &lt;/span&gt;
        index16 = ReadUInt16(); &lt;span class="cskeyword"&gt;return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineString: &amp;nbsp; token = ReadInt32(); &lt;span class="cskeyword"&gt;
                return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineSig: &amp;nbsp; &amp;nbsp;&amp;nbsp; token = ReadInt32(); &lt;span class="cskeyword"&gt;
                return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineField: &amp;nbsp;&amp;nbsp; token = ReadInt32(); &lt;span class="cskeyword"&gt;
                return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineType: &amp;nbsp; &amp;nbsp; token = ReadInt32(); &lt;span class="cskeyword"&gt;
                return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineTok: &amp;nbsp; &amp;nbsp;&amp;nbsp; token = ReadInt32(); &lt;span class="cskeyword"&gt;
                return new&lt;/span&gt; ...;&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineMethod:&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; token = ReadInt32();&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;return new&lt;/span&gt; InlineMethodInstruction(m_enclosingMethod,
        offset, opCode, token);&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;case &lt;/span&gt;&lt;span class="cstype"&gt;
            OperandType&lt;/span&gt;.InlineSwitch:&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Int32 &lt;/span&gt;cases = ReadInt32();&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Int32&lt;/span&gt;[] deltas = &lt;span
            class="cskeyword"&gt;new &lt;/span&gt;&lt;span class="cstype"&gt;Int32&lt;/span&gt;[cases];&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;for &lt;/span&gt;(&lt;span class="cstype"&gt;Int32
        &lt;/span&gt;i = 0; i &amp;lt; cases; i++) deltas[i] = ReadInt32();&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;return new&lt;/span&gt; InlineSwitchInstruction(m_enclosingMethod,
        offset, opCode, deltas);&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;default&lt;/span&gt;:&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;throw new&lt;/span&gt; BadImageFormatException(&lt;span
            class="csstring"&gt;"unexpected OperandType "&lt;/span&gt; + opCode.OperandType);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&amp;nbsp; }&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Byte &lt;/span&gt;ReadByte() { &lt;span class="cskeyword"&gt;return
        &lt;/span&gt;(&lt;span class="cstype"&gt;Byte&lt;/span&gt;)m_byteArray[m_position++]; }&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;SByte &lt;/span&gt;ReadSByte() { &lt;span class="cskeyword"&gt;
            return &lt;/span&gt;(&lt;span class="cstype"&gt;SByte&lt;/span&gt;)ReadByte(); }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;UInt16 &lt;/span&gt;ReadUInt16() { m_position += 2;
        &lt;span class="cskeyword"&gt;return &lt;/span&gt;&lt;span class="cstype"&gt;BitConverter&lt;/span&gt;.ToUInt16(m_byteArray,
        m_position - 2); }&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;UInt32 &lt;/span&gt;ReadUInt32() { m_position += 4;
        &lt;span class="cskeyword"&gt;return &lt;/span&gt;&lt;span class="cstype"&gt;BitConverter&lt;/span&gt;.ToUInt32(m_byteArray,
        m_position - 4); }&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;UInt64 &lt;/span&gt;ReadUInt64() { m_position += 8;
        &lt;span class="cskeyword"&gt;return &lt;/span&gt;&lt;span class="cstype"&gt;BitConverter&lt;/span&gt;.ToUInt64(m_byteArray,
        m_position - 8); }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Int32 &lt;/span&gt;ReadInt32() { m_position += 4; &lt;span
            class="cskeyword"&gt;return &lt;/span&gt;&lt;span class="cstype"&gt;BitConverter&lt;/span&gt;.ToInt32(m_byteArray,
        m_position - 4); }&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Int64 &lt;/span&gt;ReadInt64() { m_position += 8; &lt;span
            class="cskeyword"&gt;return &lt;/span&gt;&lt;span class="cstype"&gt;BitConverter&lt;/span&gt;.ToInt64(m_byteArray,
        m_position - 8); }&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Single &lt;/span&gt;ReadSingle() { m_position += 4;
        &lt;span class="cskeyword"&gt;return &lt;/span&gt;&lt;span class="cstype"&gt;BitConverter&lt;/span&gt;.ToSingle(m_byteArray,
        m_position - 4); }&lt;br /&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Double &lt;/span&gt;ReadDouble() { m_position += 8;
        &lt;span class="cskeyword"&gt;return &lt;/span&gt;&lt;span class="cstype"&gt;BitConverter&lt;/span&gt;.ToDouble(m_byteArray,
        m_position - 8); }&lt;br /&gt;
        }
    &lt;/div&gt;
    &lt;p&gt;
        Few comments here:
    &lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;Definitions for ILInstruction and others derived XXXInstructions are not included
            here. Imagine ILInstruction (need) knows Offset, OpCode, ...; and the derived ILInstructions
            may contain other information. If only OpCode.Call or OpCode.CallVirt (which belong
            to OperandType.InlineMethod case) was interesting to me, I'd like to define special
            CallInstruction or CallVirtInstruction class, and create them explicitly. Module.ResolveMethod
            can then help to get MethodBase from the operand (token). Yiru's &lt;a HREF="/yirutang/"&gt;
                blog&lt;/a&gt; has some posts related to this topic. &lt;/li&gt;
        &lt;li&gt;The static constructor of ILReader uses Reflection to initialize 2 static OpCode
            arrays from the enum type OpCodes. As I mentioned &lt;a HREF="/haibo_luo/archive/2005/08/28/457318.aspx"&gt;
                here&lt;/a&gt;, we may use Enum.GetValues to achieve this too. &lt;/li&gt;
        &lt;li&gt;The public constructor accepts a MethodInfo, gets its MethodBody, and then calls
            GetILAsByteArray() to set m_byteArray. Note calling GetMethodBody on the interface
            method and others could return null. &lt;/li&gt;
        &lt;li&gt;The Next() method takes advantage of OpCode.OperandType to decide what kind of operand
            is expected, how many bytes should be read. &lt;/li&gt;
        &lt;li&gt;BitConverter.ToXXX can read a number of bytes and convert them to primitive values
            in-place. Very handy! &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;
        Then I can consume the ILInstruction sequence in C# as follows:
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;foreach &lt;/span&gt;(&lt;span class="cstype"&gt;ILInstruction &lt;/span&gt;
        il &lt;span class="cskeyword"&gt;in new &lt;/span&gt;&lt;span class="cstype"&gt;ILReader&lt;/span&gt;(method))
        { &lt;span class="cscomment"&gt;/* do something with il */&lt;/span&gt; }
    &lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=476242" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><item><title>Nested Types in Generic Classes</title><link>http://blogs.msdn.com/haibo_luo/archive/2005/09/28/474970.aspx</link><pubDate>Wed, 28 Sep 2005 21:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474970</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/474970.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=474970</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=474970</wfw:comment><description>    &lt;p&gt;
        In C#, nested types can be defined in generic classes just like they would be in
        non-generic classes. For example:
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;class &lt;/span&gt;&lt;span class="cstype"&gt;G&lt;/span&gt;&amp;lt;T&amp;gt; {&lt;br /&gt;
        &amp;nbsp; &lt;span class="cskeyword"&gt;public class &lt;/span&gt;NestedC { }&lt;br /&gt;
        &amp;nbsp; &lt;span class="cskeyword"&gt;public enum&lt;/span&gt; NestedEnum { A, B }&lt;br /&gt;
        }
    &lt;/div&gt;
    &lt;p&gt;
        Inside the nested type NestedC, we can still use type parameter T, which was "declared"
        with class G&amp;lt;T&amp;gt;. Actually this is a misconception (the C# compiler does some
        magic behind the scenes). If we were to use ildasm to view the node of NestedC,
        we would find "NestedC" is a generic type with type parameter "T". As far as the
        runtime is concerned, this "T" is not the same as the "T" with G&amp;lt;T&amp;gt;; they
        just happen to have the same name.
    &lt;/p&gt;
    &lt;div class="ilcode"&gt;
        .class private auto ansi beforefieldinit G`1&amp;lt;T&amp;gt;&lt;br /&gt;
        &amp;nbsp; extends [mscorlib]System.Object&lt;br /&gt;
        {&lt;br /&gt;
        &amp;nbsp; .class auto ansi nested public beforefieldinit NestedC&lt;span class="csstring"&gt;&amp;lt;T&amp;gt;&lt;/span&gt;
        &lt;br /&gt;
        &amp;nbsp; &amp;nbsp; extends [mscorlib]System.Object&lt;br /&gt;
        &amp;nbsp; { &amp;nbsp; ...
    &lt;/div&gt;
    &lt;p&gt;
        When we use T inside NestedC, we are in fact referring to NestedC's own T, the type
        parameter "T" declared with NestedC&amp;lt;T&amp;gt;. With that in mind, let us think about
        what the following code will print:
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;class Test&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; &lt;span class="cstype"&gt;Type &lt;/span&gt;type1 = &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span
            class="cstype"&gt;G&lt;/span&gt;&amp;lt;&lt;span class="cskeyword"&gt;int&lt;/span&gt;&amp;gt;.&lt;span class="cstype"&gt;NestedC&lt;/span&gt;);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(type1);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(type1.IsGenericTypeDefinition);&lt;br /&gt;
        &amp;nbsp;&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Type &lt;/span&gt;type2 = typeof(&lt;span class="cstype"&gt;G&lt;/span&gt;&amp;lt;&lt;span
            class="cskeyword"&gt;int&lt;/span&gt;&amp;gt;).GetNestedType(&lt;span class="csstring"&gt;"NestedC"&lt;/span&gt;);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(type2);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(type2.IsGenericTypeDefinition);&lt;br /&gt;
        &amp;nbsp; }&lt;br /&gt;
        }
    &lt;/div&gt;
    &lt;p&gt;
        1. typeof(G&amp;lt;int&amp;gt;.NestedC) is translated by C# compiler to
    &lt;/p&gt;
    &lt;div class="ilcode"&gt;
        &amp;nbsp; IL_0001:&amp;nbsp; ldtoken &amp;nbsp;&amp;nbsp; class G`1/NestedC&amp;lt;int32&amp;gt;&lt;br /&gt;
        &amp;nbsp; IL_0006:&amp;nbsp; call &amp;nbsp; &amp;nbsp; class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype
        [mscorlib]System.RuntimeTypeHandle)
    &lt;/div&gt;
    &lt;p&gt;
        The generic argument "int32" is bound to NestedC&amp;lt;&amp;gt;, not G&amp;lt;&amp;gt;;
    &lt;/p&gt;
    &lt;p&gt;
        2. You might already have noticed that although both are generic types, "NestedC"
        does not have `(grave accent), but "G`1" does. So typeof(G&amp;lt;int&amp;gt;).GetNestedType("NestedC")
        will get back the open generic type "NestedC&amp;lt;&amp;gt;".
        &lt;br /&gt;
    &lt;/p&gt;
    &lt;p&gt;
        Here is the result, is it as you expected?
    &lt;/p&gt;
    &lt;p&gt;
        &lt;span style="font-family: Courier"&gt;&amp;nbsp;&amp;nbsp; G`1+NestedC[System.Int32]&lt;br /&gt;
            &amp;nbsp;&amp;nbsp; False&lt;br /&gt;
            &amp;nbsp;&amp;nbsp; G`1+NestedC[T]&lt;br /&gt;
            &amp;nbsp;&amp;nbsp; True &lt;/span&gt;
    &lt;/p&gt;
    &lt;p&gt;
        In summary, when written in C#, every type defined under a generic type will be
        a generic type (including enum; C# does not allow us to explicitly define a generic
        enum). To define a truly non-generic nested type inside a generic type, IL can help:
    &lt;/p&gt;
    &lt;div class="ilcode"&gt;
        .class private auto ansi beforefieldinit G`1&amp;lt;T&amp;gt;&lt;br /&gt;
        &amp;nbsp; extends [mscorlib]System.Object&lt;br /&gt;
        {&lt;br /&gt;
        &amp;nbsp; .class auto ansi nested public beforefieldinit &lt;span class="csstring"&gt;NestedNonGenericC&lt;/span&gt;
        &lt;br /&gt;
        &amp;nbsp; &amp;nbsp; extends [mscorlib]System.Object&lt;br /&gt;
        &amp;nbsp; {&amp;nbsp; ...
    &lt;/div&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=474970" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><item><title>No LocalVariableInfo.Name?</title><link>http://blogs.msdn.com/haibo_luo/archive/2005/09/02/460369.aspx</link><pubDate>Sat, 03 Sep 2005 05:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:460369</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/460369.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=460369</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=460369</wfw:comment><description>    &lt;p&gt;
        This was &lt;a href="http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?feedbackid=e8735065-ed2d-443d-a7c4-af3700459cf1"&gt;
            one ladybug&lt;/a&gt; in MSDN product feedback center. First of all, thanks to those
        who filed bugs or suggestions through it, which really help improve our product
        quality.
    &lt;/p&gt;
    &lt;p&gt;
        No Name property in the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.LocalVariableInfo.aspx"&gt;
            LocalVariableInfo&lt;/a&gt; class is "by design" (possibly forever). Inside a .Net
        assembly, there is no metadata (or table) keeping this information. However, sometimes
        when using ildasm to view the method, we do see those local variable names, such
        as
    &lt;/p&gt;
    &lt;div class="ilcode"&gt;
        .locals init ([0] int32 m_int32,&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[1] object m_object,&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[2] int32[] m_array,&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[3] int32[] CS$0$0000)
    &lt;/div&gt;
    &lt;p&gt;
        Those names are from the pdb file, not embedded in the exe or dll. If we move the
        pdb to other directory, and open the ildasm again, we will see those variable names
        become to V_0, V_1...
    &lt;/p&gt;
    &lt;div class="ilcode"&gt;
        .locals init (int32 V_0,&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;object V_1,&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;int32[] V_2,&lt;br /&gt;
        &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;int32[] V_3)
    &lt;/div&gt;
    &lt;p&gt;
        If you *really* need those names in your managed application, you may want to take
        a look at &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=38449a42-6b7a-4e28-80ce-c55645ab1310&amp;displaylang=en"&gt;
            Mdbg source codes&lt;/a&gt;; but here are the general steps to get it:
    &lt;/p&gt;
    &lt;ol&gt;
        &lt;li&gt;Get IMetaDataImport, say &lt;i&gt;import&lt;/i&gt; (I found examples &lt;a href="http://pzsolt.blogspot.com/2005/01/reading-types-from-assembly.html"&gt;
            here&lt;/a&gt; or &lt;a HREF="/joelpob/archive/2004/09.aspx"&gt;here&lt;/a&gt;);
        &lt;/li&gt;
        &lt;li&gt;Call Marshal.GetComInterfaceForObject(&lt;i&gt;import&lt;/i&gt;, typeof(IMetaDataImport)) to
            get the raw interface IntPtr; &lt;/li&gt;
        &lt;li&gt;Call new SymBinder().GetReader() with that IntPtr to get ISymbolReader &lt;/li&gt;
        &lt;li&gt;Call ISymbolReader.GetMethod() on the SymbolToken, which is constructed based on
            the MetadataToken of the method you want to get local variable names, and get back
            ISymMethod &lt;/li&gt;
        &lt;li&gt;Then play with ISymMethod.RootScope, ISymbolScope.GetChildren(), ISymbolScope.GetLocals();
        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p&gt;
        Yes, there is ISymbolVariable.Name.
        &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=460369" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><item><title>Get Names and Values of Enum Members</title><link>http://blogs.msdn.com/haibo_luo/archive/2005/08/28/457318.aspx</link><pubDate>Sun, 28 Aug 2005 21:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:457318</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/457318.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=457318</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=457318</wfw:comment><description>    &lt;p&gt;
        Yes, reflection can get this done. Assume we have an Enum type - Colors, the following
        code will print the name and value for each member of it.
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;foreach &lt;/span&gt;(&lt;span class="cstype"&gt;FieldInfo &lt;/span&gt;fi
        in &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;Colors&lt;/span&gt;).GetFields(&lt;span
            class="cstype"&gt;BindingFlags&lt;/span&gt;.Public | &lt;span class="cstype"&gt;BindingFlags&lt;/span&gt;.Static))&lt;br /&gt;
        {&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(fi.Name);&lt;br /&gt;
        &amp;nbsp; &amp;nbsp;&lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(fi.GetValue(&lt;span class="cskeyword"&gt;null&lt;/span&gt;));&lt;br /&gt;
        }&lt;br /&gt;
    &lt;/div&gt;
    &lt;p&gt;
        Note we need to specify BindingFlags.Static explicitly here; Otherwise, both static
        and instance fields will get returned, including the special instance field "value__".
    &lt;/p&gt;
    &lt;p&gt;
        In fact, BCL provides more neat (and maybe faster) APIs to achieve this:
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;string&lt;/span&gt;[] names = &lt;span class="cstype"&gt;Enum&lt;/span&gt;.GetNames(&lt;span
            class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;Colors&lt;/span&gt;));&lt;br /&gt;
        &lt;span class="cstype"&gt;Colors&lt;/span&gt;[] values = (&lt;span class="cstype"&gt;Colors&lt;/span&gt;[])&lt;span
            class="cstype"&gt;Enum&lt;/span&gt;.GetValues(&lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span
                class="cstype"&gt;Colors&lt;/span&gt;));
    &lt;/div&gt;
    &lt;p&gt;
        If the enum type we are exploring is loaded in &lt;a HREF="/joelpob/archive/2004/06/22/163206.aspx"&gt;
            the ReflectionOnly context&lt;/a&gt;, calling FieldInfo.GetValue will throw "InvalidOperationException:
        Code execution is prohibited in an assembly loaded as ReflectionOnly", since GetValue
        tries to &lt;i&gt;create&lt;/i&gt; an object of the enum type and return it. Same for Enum.GetValues.
    &lt;/p&gt;
    &lt;p&gt;
        The new API in FieldInfo:
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;public virtual object&lt;/span&gt; GetRawConstantValue();
    &lt;/div&gt;
    &lt;p&gt;
        could be what you need in such scenarios. It will return the value of enum's underlying
        &lt;i&gt;integer&lt;/i&gt; type. For example, if the underlying type of enum "Colors" is byte,
        fi.&lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.fieldinfo.getrawconstantvalue.aspx"&gt;GetRawConstandValue&lt;/a&gt;()
        will return a boxed byte.
    &lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=457318" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item><item><title>Reflection and Nullable&lt;T&gt;</title><link>http://blogs.msdn.com/haibo_luo/archive/2005/08/23/455241.aspx</link><pubDate>Tue, 23 Aug 2005 10:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:455241</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/455241.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=455241</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=455241</wfw:comment><description>    &lt;p&gt;
        You might have already read &lt;a href="http://blogs.msdn.com/somasegar/archive/2005/08/11/450640.aspx" mce_href="http://blogs.msdn.com/somasegar/archive/2005/08/11/450640.aspx"&gt;
            this&lt;/a&gt;: VS2005 made the last-minute DCR related to boxed Nullable&amp;lt;T&amp;gt;.
        Runtime now treats Nullable&amp;lt;T&amp;gt; differently from other generic value types
        when boxing:
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cstype"&gt;Int32&lt;/span&gt;? x = &lt;span class="cskeyword"&gt;null&lt;/span&gt;;&lt;br&gt;
        &lt;span class="cskeyword"&gt;object&lt;/span&gt; y = x;&amp;nbsp; &lt;span class="cscomment"&gt;
            &lt;br&gt;
            // y is simply null, not a truly boxed "nullable&amp;lt;int&amp;gt; struct" (which then
            tells it has no value)&lt;/span&gt;
    &lt;/div&gt;
    &lt;p&gt;
        And&lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cstype"&gt;Int32 &lt;/span&gt;? x = 100;
        &lt;br&gt;
        &lt;span class="cskeyword"&gt;object &lt;/span&gt;y = x;&amp;nbsp;
        &lt;br&gt;
        &lt;span class="cscomment"&gt;// y is boxed Int32 100 (same as "object y = 100"), no longer
            a boxed "nullable&amp;lt;int&amp;gt; struct" with a field of value 100.&lt;/span&gt;
    &lt;/div&gt;
    &lt;p&gt;
        Reflection late-bind invocation always deals with "object"; value type instances
        are always getting boxed first before invocation. One of such APIs: PropertyInfo.SetValue(Object
        obj, &lt;i&gt;&lt;span style="text-decoration: underline;"&gt;Object&lt;/span&gt;&lt;/i&gt; value, Object[]
        index). There was &lt;a href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=15304" mce_href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=15304"&gt;
            one question&lt;/a&gt; in Microsoft Technical Forums: Exception is thrown when setting
        DateTime value to a property with type Nullable&amp;lt;DateTime&amp;gt;. With this DCR change,
        such late-bind calls can be written in a more natural way.
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cskeyword"&gt;class &lt;/span&gt;&lt;span class="cstype"&gt;C&lt;/span&gt;&lt;br&gt;
        {&lt;br&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Int32&lt;/span&gt;? m_field;&lt;br&gt;
        &amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public &lt;/span&gt;&lt;span class="cstype"&gt;Int32&lt;/span&gt;?
        Property&lt;br&gt;
        &amp;nbsp;&amp;nbsp; {&lt;br&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;get &lt;/span&gt;{ &lt;span class="cskeyword"&gt;return &lt;/span&gt;
        m_field; }&lt;br&gt;
        &amp;nbsp; &amp;nbsp; &lt;span class="cskeyword"&gt;set &lt;/span&gt;{ m_field = &lt;span class="cskeyword"&gt;
            value&lt;/span&gt;; }&lt;br&gt;
        &amp;nbsp;&amp;nbsp; }&lt;br&gt;
        }&lt;br&gt;
        &lt;br&gt;
        &lt;span class="cstype"&gt;PropertyInfo &lt;/span&gt;pi = &lt;span class="cskeyword"&gt;typeof&lt;/span&gt;(&lt;span class="cstype"&gt;C&lt;/span&gt;).GetProperty(&lt;span class="csstring"&gt;"Property"&lt;/span&gt;);&lt;br&gt;
        &lt;span class="cstype"&gt;C&lt;/span&gt; c = &lt;span class="cskeyword"&gt;new &lt;/span&gt;C();&lt;br&gt;
        pi.SetValue(c, 100, &lt;span class="cskeyword"&gt;null&lt;/span&gt;); &lt;span class="cscomment"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
            // works&lt;/span&gt;&lt;br&gt;
        pi.SetValue(c, (&lt;span class="cstype"&gt;Int32&lt;/span&gt;?)100, &lt;span class="cskeyword"&gt;null&lt;/span&gt;);
        &lt;span class="cscomment"&gt;// no longer have to write like this&lt;/span&gt;&lt;/div&gt;
    &lt;p&gt;
        After boxing, 100 and (Int32?)100 are the same thing: boxed Int32 object. There
        is no more boxed object with type "Int32?"; late-invocation has to accept it and
        set to Int32? property. Or think it this way, runtime can not tell where a boxed
        Int32 object was originally from: either just Int32 instance or Int32? instance;
        it is reasonable to allow setting a boxed Int32 object to field/property of either
        Int32 or Int32? type (same for argument pass-in when doing method invocation)
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        pi.SetValue(c, &lt;span class="cskeyword"&gt;null&lt;/span&gt;, &lt;span class="cskeyword"&gt;null&lt;/span&gt;);
        &lt;span class="cscomment"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // works&lt;/span&gt;&lt;/div&gt;
    &lt;p&gt;
        This actually worked before the DCR. And ,
    &lt;/p&gt;
    &lt;div class="csharp"&gt;
        &lt;span class="cstype"&gt;Object &lt;/span&gt;ret = pi.GetValue(c,&lt;span class="cskeyword"&gt; null&lt;/span&gt;);
    &lt;/div&gt;
    &lt;p&gt;
        ret will be either boxed Int32 object or simply null. There is no problem in casting
        the result to Int32? type.
    &lt;/p&gt;
    &lt;p&gt;
        Here are some reflection behavior changes as a result of this DCR:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;Probably the most important one is "typeof(T?).IsAssignableFrom(typeof(T)) == true".
            PropertyInfo.SetValue/GetValue use this first to ensure the pass-in value is assignable
            to Nullable&amp;lt;T&amp;gt; property. &lt;/li&gt;
        &lt;li&gt;Object.GetType() will never get back any type of Nullable&amp;lt;T&amp;gt;. Joe had an interesting
            &lt;a href="http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=d896018c-c648-41bb-90f5-11d09fbf4065" mce_href="http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=d896018c-c648-41bb-90f5-11d09fbf4065"&gt;
                post&lt;/a&gt; on this. &lt;/li&gt;
        &lt;li&gt;Activator.CreateInstance could never be expected to return null before; with this
            DCR, it will return null when creating instance of type Nullable&amp;lt;T&amp;gt; but not
            providing non-null T value. For example, Activator.CreateInstance(typeof(Int32?))
            returns null. &lt;/li&gt;
    &lt;/ul&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=455241" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection/default.aspx">Reflection</category></item></channel></rss>