<?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.Emit</title><link>http://blogs.msdn.com/haibo_luo/archive/tags/Reflection.Emit/default.aspx</link><description>Tags: Reflection.Emit</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>DebuggerTypeProxy for IronPython Old-style Class and Instance</title><link>http://blogs.msdn.com/haibo_luo/archive/2007/08/03/4210344.aspx</link><pubDate>Fri, 03 Aug 2007 22:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4210344</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/4210344.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=4210344</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=4210344</wfw:comment><description>&lt;P&gt;First I want to make it clear that this post means nothing related to IronPython's plan about debugging python code in the future; it serves more as an interesting example to demonstrate &lt;A href="http://msdn2.microsoft.com/en-us/library/d8eyd8zc.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/d8eyd8zc.aspx"&gt;DebuggerTypeProxyAttribute&lt;/A&gt; and how types can be created dynamically and be used in the VS debugger windows to display information the end users are interested in.&lt;/P&gt;
&lt;P&gt;The python code below shows one old style class and some operations on the instance. After downloading the binary zip of &lt;A href="http://www.codeplex.com/IronPython/Release/ProjectReleases.aspx?ReleaseId=3749" target=_blank mce_href="http://www.codeplex.com/IronPython/Release/ProjectReleases.aspx?ReleaseId=3749"&gt;IronPython 2.0 Alpha 3&lt;/A&gt;, we can create a solution, set it to launch ipy.exe for debugging, and step through the code inside Visual Studio; the locals window may show something like this after hitting the breakpoint.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withoutproxy-final.jpg" mce_href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withoutproxy-final.jpg" atomicselection="true"&gt;&lt;IMG height=538 alt=withoutproxy-final src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withoutproxy-final_thumb.jpg" width=541 border=0 mce_src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withoutproxy-final_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The local variable &lt;I&gt;alpha3&lt;/I&gt;'s .NET type is IronPython.Runtime.Types.OldInstance, the way this object is displayed in the locals window is based on that type's fields and properties, which exposes many implementation details. While debugging, what the python users really want to know is the object attributes. My goal is to make python object attributes look like C# object's public fields; how can I achieve this?&lt;/P&gt;
&lt;P&gt;DebuggerTypeProxyAttribute allows us to specify a proxy type for the target type. VS debugger uses the proxy type to display the target object. We already see such proxy types a lot: when viewing objects of most collection types, we are actually viewing their proxy type layouts. &lt;/P&gt;
&lt;P&gt;In current IronPython implementation, every old style instance is of type I.R.T.OldInstance, so my first step is to define a proxy type "OldInstanceProxy" to expose the object attributes only. Clearly old style instances can have different attribute set of different names; but I can only specify one proxy type for the I.R.T.OldInstance type. [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] is part of the solution to achieve the look-and-feel. The proxy type (OldInstanceProxy) has an object field (&lt;EM&gt;m_oldInstance&lt;/EM&gt;) decorated with that attribute so that &lt;EM&gt;m_oldInstance&lt;/EM&gt; will be hiden in the debugger window, but the fields &lt;EM&gt;m_oldInstance&lt;/EM&gt; has will be shown. What should &lt;EM&gt;m_oldInstance&lt;/EM&gt; look like? A .NET type (let me call it the "real" proxy type) with as many public fields as python object attributes, each having the same name as the attribute name, and we are going to create such types on the fly. Also the "real" proxy type's constructor is emitted with the code to assign these public fields properly. We then instantiate the new type with the original OldInstance object, and assign it to &lt;EM&gt;m_oldInstance&lt;/EM&gt;. &lt;/P&gt;
&lt;DIV class=csharp&gt;[assembly:&lt;SPAN class=cstype&gt;DebuggerTypeProxy&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;&lt;BR&gt;&amp;nbsp; typeof&lt;/SPAN&gt;(IronPython.DebuggingSupport.&lt;SPAN class=cstype&gt;OldInstanceProxy&lt;/SPAN&gt;),&lt;BR&gt;&amp;nbsp;&amp;nbsp;TargetTypeName = &lt;SPAN class=csstring&gt;"IronPython.Runtime.Types.OldInstance, IronPython, Version=2.0.0.300, ..."&lt;/SPAN&gt;)&lt;BR&gt;]&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;public class &lt;/SPAN&gt;&lt;SPAN class=cstype&gt;OldInstanceProxy&lt;/SPAN&gt;{&lt;BR&gt;&amp;nbsp; [&lt;SPAN class=cstype&gt;DebuggerBrowsable&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DebuggerBrowsableState&lt;/SPAN&gt;.RootHidden)]&lt;BR&gt;&amp;nbsp; &lt;SPAN class=cskeyword&gt;public object &lt;/SPAN&gt;m_oldInstance;&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;SPAN class=cskeyword&gt;public &lt;/SPAN&gt;OldInstanceProxy(&lt;SPAN class=cskeyword&gt;object &lt;/SPAN&gt;target) {&lt;BR&gt;&amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;try &lt;/SPAN&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;SPAN class=cstype&gt;OldInstance &lt;/SPAN&gt;obj = target &lt;SPAN class=cskeyword&gt;as&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;OldInstance&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cstype&gt;TypeBuilder &lt;/SPAN&gt;tb = CodeGen.CreateTemporaryType();&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cstype&gt;ConstructorBuilder &lt;/SPAN&gt;cb = tb.DefineConstructor(&lt;SPAN class=cstype&gt;MethodAttributes&lt;/SPAN&gt;.Public, &lt;SPAN class=cstype&gt;CallingConventions&lt;/SPAN&gt;.Standard, &lt;SPAN class=cskeyword&gt;new &lt;/SPAN&gt;&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;OldInstance&lt;/SPAN&gt;) });&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cstype&gt;ILGenerator &lt;/SPAN&gt;il = cb.GetILGenerator();&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; il.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ldarg_0);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; il.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Call, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;Object&lt;/SPAN&gt;).GetConstructor(&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.EmptyTypes));&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;foreach &lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;KeyValuePair&lt;/SPAN&gt;&amp;lt;&lt;SPAN class=cskeyword&gt;object&lt;/SPAN&gt;,&lt;SPAN class=cskeyword&gt;object&lt;/SPAN&gt;&amp;gt; pair &lt;SPAN class=cskeyword&gt;in &lt;/SPAN&gt;obj.Dictionary) {&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;string &lt;/SPAN&gt;key = pair.Key.ToString();&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cstype&gt;Type &lt;/SPAN&gt;fieldType = pair.Value == &lt;SPAN class=cskeyword&gt;null &lt;/SPAN&gt;? &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;object&lt;/SPAN&gt;) : pair.Value.GetType();&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cstype&gt;FieldBuilder &lt;/SPAN&gt;fb = tb.DefineField(key, fieldType, &lt;SPAN class=cstype&gt;FieldAttributes&lt;/SPAN&gt;.Pub.Public);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cscomment&gt;// emit code for the ctor ...&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; il.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ret);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_oldInstance = &lt;SPAN class=cstype&gt;Activator&lt;/SPAN&gt;.CreateInstance(tb.CreateType(), obj);&lt;BR&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Few discussions:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The attached solution also includes another proxy type: OldClassProxy for IronPython.Runtime.Types.OldClass. With that, viewing class attributes feels like viewing C# class static fields. Such coding pattern can be applied to other similar scenarios. 
&lt;LI&gt;It is a bit hard to apply this for IronPython new style instances. For each new style class, IronPython creates a new type on the fly. For example, "class C(object): pass" generates a IronPython.Runtime.NewTypes.Object_1. The proxy type (which will create the "real" proxy type) &amp;nbsp;need be created at the same time. 
&lt;LI&gt;Types created by Reflection.Emit are not GC-collectible. In my proxy type implementation,&amp;nbsp;a simple&amp;nbsp;caching mechanism is implemented to reuse those "real" proxy types; but considering the python dynamism, object attributes can be added, removed, their values' type can be changed; such "real" proxy type may have to be created frequently, each click to expand in the debugger window could cause one type creation, so use wisely if you use such proxy type in real world scenarios.&amp;nbsp;&amp;nbsp; 
&lt;LI&gt;Unlike DebuggerVisualizer where VS provides a way to debug it, it is a bit inconvenient to debug DebuggerTypeProxy code. So I found having the constructor code wrapped inside try-catch and saving the exception if thrown is useful. The exception object can be viewed in the debugger window if the type proxy dll is compiled with the "Debug" configuration.&amp;nbsp; The messages from Debug.WriteLine are helpful too. 
&lt;LI&gt;The proxy type implementation depends on the rapidly changing code of the DLR/IronPython project. It is not surprising that the attached solution could be broken in the future. . &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The following pictures show the proxy type in action. Compared to the previous picture, now you can easily check out the values of the attribute "url" and "version", as well as the class attribute "project_name"&amp;nbsp;(shown in the first picture). The new attribute "release_date" appears in the second picture after stepping through the breakpoint line. &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withproxy1.jpg" mce_href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withproxy1.jpg" atomicselection="true"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=319 alt=withproxy1 src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withproxy1_thumb.jpg" width=574 border=0 mce_src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withproxy1_thumb.jpg"&gt;&lt;/A&gt;&lt;A href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withproxy2.jpg" mce_href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withproxy2.jpg" atomicselection="true"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=244 alt=withproxy2 src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withproxy2_thumb.jpg" width=574 border=0 mce_src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/Debugger_E941/withproxy2_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;To use the attached solution, you need download IronPython 2.0 alpha 3 binary zip, and I assume you unzip it to C:\. Your comments are welcome.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4210344" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/4210344.ashx" length="8704" type="application/x-zip-compressed" /><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/IronPython/default.aspx">IronPython</category></item><item><title>Always Peverify IL Code of your Dynamic Method</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/10/31/always-peverify-il-code-of-your-dynamic-method.aspx</link><pubDate>Wed, 01 Nov 2006 07:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1038287</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/1038287.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=1038287</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=1038287</wfw:comment><description>&lt;P&gt;Current dynamic method implementation does not have built-in support to pre-check whether the dynamic method code is verifiable. With bad IL sequence, very often you will get "System.&lt;A href="http://msdn2.microsoft.com/en-us/library/system.invalidprogramexception.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.invalidprogramexception.aspx"&gt;InvalidProgramException&lt;/A&gt;: Common Language Runtime detected an invalid program" when it gets executed. See the code example below, where C1, C2 are 2 simple reference types. Btw I understand only me write such "fun" IL code.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;LocalBuilder&lt;/SPAN&gt; lb = ilgen.DeclareLocal(&lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(C2));&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Newobj, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(C1).GetConstructor(&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.EmptyTypes));&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Stloc_0, lb);&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ldc_I4_0); &lt;BR&gt;ilgen.EmitWriteLine(&lt;SPAN class=csstring&gt;"I got called"&lt;/SPAN&gt;);&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ret);&lt;/DIV&gt;
&lt;P&gt;Even if you did not get InvalidProgramException, it does not mean the code-gen is correct. When the following code get invoked, "I got called too" will be printed; but the code is not verifiable. When the SkipVerification permission is refused, executing this dynamic method causes JIT to verify first: "System.Security.&lt;A href="http://msdn2.microsoft.com/en-us/library/system.security.verificationexception.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.security.verificationexception.aspx"&gt;VerficationException&lt;/A&gt;: Operation could destabilize the runtime" throws. &lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;LocalBuilder&lt;/SPAN&gt; lb = ilgen.DeclareLocal(&lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(C2));&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Newobj, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(C1).GetConstructor(&lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.EmptyTypes));&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Stloc_0, lb);&lt;BR&gt;ilgen.EmitWriteLine(&lt;SPAN class=csstring&gt;"I got called too"&lt;/SPAN&gt;);&lt;BR&gt;ilgen.Emit(&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;.Ret);&lt;/DIV&gt;
&lt;P&gt;However both exception messages contain no much useful information: they do not tell which instruction could be blamed. For any production code using DynamicMethod, to ensure the code-gen quality, it is a good practice to have another implementation which have Reflection.Emit to emit the same IL code to disk, and call Peverify.exe to verify it. &lt;A href="http://www.codeplex.com/ironpython" mce_href="http://www.codeplex.com/ironpython"&gt;IronPython&lt;/A&gt;'s code-gen has both approaches: at the beginning when we enforced this check, we caught several code-gen issues. This is what peverify.exe shows for the 2 scenarios above:&lt;/P&gt;
&lt;DIV class=csharp&gt;[IL]: Error: [D:\snippets.dll : Sample::M][offset 0x00000005][found ref 'C1'][expected ref 'C2'] Unexpected type on the stack.&lt;BR&gt;[IL]: Error: [D:\snippets.dll : Sample::M][offset 0x00000011] Stack must be empty on return from a void function.&lt;BR&gt;----&lt;BR&gt;[IL]: Error: [D:\snippets.dll : Sample::M][offset 0x00000005][found ref 'C1'][expected ref 'C2'] Unexpected type on the stack.&lt;BR&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1038287" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection.Emit/default.aspx">Reflection.Emit</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>ILGenerator.EmitCall Mainly For vararg Methods</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/08/13/698719.aspx</link><pubDate>Mon, 14 Aug 2006 02:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:698719</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/698719.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=698719</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=698719</wfw:comment><description>&lt;P&gt;Vararg (variable arguments) methods accept argument lists of unknown length and type. CLR supports this by the IL instruction (arglist) and other BCL types, such as &lt;A href="http://msdn2.microsoft.com/en-US/library/System.ArgIterator.aspx"&gt;System.ArgIterator&lt;/A&gt;. C# compiler has undocumented keyword "__arglist" to support defining vararg methods, accessing variable arguments and calling them, as shown below. &lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;static void&lt;/SPAN&gt; VarargMethod(&lt;SPAN class=cskeyword&gt;string&lt;/SPAN&gt; headline, &lt;SPAN class=cskeyword&gt;__arglist&lt;/SPAN&gt;) {&lt;BR&gt;&amp;nbsp; &lt;SPAN class=cskeyword&gt;ArgIterator&lt;/SPAN&gt; ai = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ArgIterator&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;__arglist&lt;/SPAN&gt;);&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp; &lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.Write(headline);&lt;BR&gt;&amp;nbsp; &lt;SPAN class=cskeyword&gt;while&lt;/SPAN&gt; (ai.GetRemainingCount() &amp;gt; 0)&lt;BR&gt;&amp;nbsp; &amp;nbsp; &lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN class=cstype&gt;TypedReference&lt;/SPAN&gt;.ToObject(ai.GetNextArg()));&lt;BR&gt;&amp;nbsp; &amp;nbsp; &lt;SPAN class=cstype&gt;Console&lt;/SPAN&gt;.WriteLine();&lt;BR&gt;}&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;static void&lt;/SPAN&gt; CallVarargMethod() {&lt;BR&gt;&amp;nbsp; VarargMethod(&lt;SPAN class=csstring&gt;"Hello world from "&lt;/SPAN&gt;, &lt;SPAN class=cskeyword&gt;__arglist&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;Assembly&lt;/SPAN&gt;.GetExecutingAssembly()));&lt;BR&gt;&amp;nbsp; VarargMethod(&lt;SPAN class=csstring&gt;"Current time: "&lt;/SPAN&gt;, &lt;SPAN class=cskeyword&gt;__arglist&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;.Now, &lt;SPAN class=csstring&gt;" (UTC "&lt;/SPAN&gt;, &lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;.UtcNow, &lt;SPAN class=csstring&gt;")"&lt;/SPAN&gt;));&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Two&amp;nbsp;MemberRef tokens are needed to specify each vararg method call site. The blob each MemberRef points to specifies the methodref signature: types of both fixed and variable arguments. &lt;/P&gt;
&lt;DIV class=ilcode&gt;MethodName: VarargMethod (06000001)&lt;BR&gt;MemberRef #1 (0a00000c)&lt;BR&gt;&amp;nbsp; &amp;nbsp; 2 Arguments&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #1: String&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #2: &amp;lt;ELEMENT_TYPE_SENTINEL&amp;gt; Class System.Reflection.Assembly&lt;BR&gt;MemberRef #2 (0a00000f)&lt;BR&gt;&amp;nbsp; &amp;nbsp; 5 Arguments&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #1: String&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #2: &amp;lt;ELEMENT_TYPE_SENTINEL&amp;gt; ValueClass System.DateTime&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #3: String&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #4: ValueClass System.DateTime&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Argument #5: String&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-US/library/system.reflection.emit.ilgenerator.emitcall.aspx"&gt;ILGenerator.EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)&lt;/A&gt; is designed for emitting call to such vararg method (for both Reflection.Emit and dynamic method scenarios). The optionalParameterTypes argument is passed in to create different MethodRef tokens. &lt;/P&gt;
&lt;P&gt;Assume the MethodInfo of "VarargMethod" is miVarargMethod, the following code creates a DynamicMethod to perform the same functionality as previous "CallVarargMethod" does:&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cstype&gt;DynamicMethod&lt;/SPAN&gt; dm = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;DynamicMethod&lt;/SPAN&gt;(&lt;SPAN class=csstring&gt;"CallVarargMethod"&lt;/SPAN&gt;, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;void&lt;/SPAN&gt;), &lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;.EmptyTypes, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;object&lt;/SPAN&gt;));&lt;BR&gt;&lt;SPAN class=cstype&gt;ILGenerator&lt;/SPAN&gt; il = dm.GetILGenerator();&lt;BR&gt;&amp;nbsp;&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ldstr, &lt;SPAN class=csstring&gt;"Hello world from "&lt;/SPAN&gt;);&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;Assembly&lt;/SPAN&gt;).GetMethod(&lt;SPAN class=csstring&gt;"GetExecutingAssembly"&lt;/SPAN&gt;));&lt;BR&gt;il.EmitCall(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, miVarargMethod, &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;Assembly&lt;/SPAN&gt;) });&lt;BR&gt;&amp;nbsp;&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ldstr, &lt;SPAN class=csstring&gt;"Current time: "&lt;/SPAN&gt;);&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;).GetMethod(&lt;SPAN class=csstring&gt;"get_Now"&lt;/SPAN&gt;));&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ldstr, &lt;SPAN class=csstring&gt;" (UTC "&lt;/SPAN&gt;);&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;).GetMethod(&lt;SPAN class=csstring&gt;"get_UtcNow"&lt;/SPAN&gt;));&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ldstr, &lt;SPAN class=csstring&gt;")"&lt;/SPAN&gt;);&lt;BR&gt;il.EmitCall(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Call, miVarargMethod, &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;), &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;string&lt;/SPAN&gt;), &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DateTime&lt;/SPAN&gt;), &lt;SPAN class=cskeyword&gt;typeof&lt;/SPAN&gt;(&lt;SPAN class=cskeyword&gt;string&lt;/SPAN&gt;) });&lt;BR&gt;&amp;nbsp;&lt;BR&gt;il.Emit(&lt;SPAN class=cstype&gt;&lt;SPAN class=cstype&gt;OpCodes&lt;/SPAN&gt;&lt;/SPAN&gt;.Ret);&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;As you see in the attached C# code (which uses ILGenerator.EmitCall for both Reflection.Emit and DynamicMethod), Type.GetMethod (and other APIs) can return MethodInfo of vararg methods; however &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbase.invoke.aspx "&gt;MethodInfo.Invoke&lt;/A&gt; currently does not support to invoke on them. It is easy to get around with this: just&amp;nbsp;create a dynamic method, and use EmitCall, and invoke on the dynamic method.&lt;/P&gt;
&lt;P&gt;Although EmitCall can be used to emit a call to non-vararg method, you are encouraged to use &lt;A href="http://msdn2.microsoft.com/en-us/library/xz8067x2.aspx"&gt;ILGenerator.Emit(OpCode, MethodInfo)&lt;/A&gt; for that scenario, and use EmitCall mainly for vararg methods. With that said, the naming of this API does sound somewhat misleading. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=698719" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/698719.ashx" length="2807" type="text/plain" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection.Emit/default.aspx">Reflection.Emit</category><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/DynamicMethod/default.aspx">DynamicMethod</category></item><item><title>Reflection.Emit and Resources</title><link>http://blogs.msdn.com/haibo_luo/archive/2006/04/26/584629.aspx</link><pubDate>Thu, 27 Apr 2006 03:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:584629</guid><dc:creator>Haibo_Luo</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/haibo_luo/comments/584629.aspx</comments><wfw:commentRss>http://blogs.msdn.com/haibo_luo/commentrss.aspx?PostID=584629</wfw:commentRss><wfw:comment>http://blogs.msdn.com/haibo_luo/rsscomments.aspx?PostID=584629</wfw:comment><description>&lt;P&gt;Reflection.Emit is relatively new to me. Recently I had a chance to deal with a resource related emit issue and had a tough time wading through so many emit APIs with "resource" in their names. Seems they are kind of messy, and I feel the API naming is not as good as it can be. &lt;/P&gt;
&lt;P&gt;The Windows &lt;A href="http://msdn.microsoft.com/msdnmag/issues/02/03/PE2/"&gt;Portable Executable&lt;/A&gt; (PE) file format has a &lt;EM&gt;.rsrc &lt;/EM&gt;section; we normally call this section the standard Win32 resources or unmanaged resources section. Reflection.Emit was designed to support emitting the unmanaged resources to a PE file; however our customers recently told us that &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.AssemblyBuilder.DefineUnmanagedResource.aspx"&gt;AssemblyBuilder.DefineUnmanagedResource&lt;/A&gt; and &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.ModuleBuilder.DefineUnmanagedResource.aspx"&gt;ModuleBuilder.DefineUnmanagedResource&lt;/A&gt; are broken &lt;A href="http://msdn.microsoft.com/msdnmag/issues/02/03/PE2/"&gt;in&lt;/A&gt; &lt;A href="http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?feedbackid=69396185-e161-49a1-bbe5-73e228f684cd"&gt;some&lt;/A&gt; &lt;A href="http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?feedbackid=b78517cc-f22f-4eac-aad9-fd4e9e7a1b96"&gt;aspects&lt;/A&gt;. We will have to wait for the next major release to get them fixed.&lt;/P&gt;
&lt;P&gt;CLR extends the PE file format to contain CIL header and data sections (which reside in PE file's &lt;EM&gt;.text&lt;/EM&gt; section). Managed resources are stored in this section too. For a better understanding of metadata, I review the &lt;A href="http://www.ecma-international.org/publications/standards/Ecma-335.htm"&gt;ecma spec 335&lt;/A&gt;, particularly these 2 paragraphs:&lt;/P&gt;&lt;SPAN class=quotesrc&gt;From Partition II, section 6.2.2&lt;/SPAN&gt;&lt;BR&gt;
&lt;DIV class=quote&gt;A manifest resource is simply a named item of data associated with an assembly. A manifest resource is introduced using the &lt;SPAN class=inlinecode&gt;.mresource&lt;/SPAN&gt; directive, which adds the manifest resource to the assembly manifest begun by a preceding &lt;SPAN class=inlinecode&gt;.assembly&lt;/SPAN&gt; declaration. &lt;/DIV&gt;&lt;SPAN class=quotesrc&gt;From Partition II, section 22.24&lt;/SPAN&gt;&lt;BR&gt;
&lt;DIV class=quote&gt;The ManifestResource table has the following columns:&amp;nbsp; 
&lt;UL&gt;
&lt;LI&gt;Offset (a 4-byte constant) 
&lt;LI&gt;Flags (a 4-byte bitmask of type ManifestResourceAttributes) 
&lt;LI&gt;Name (an index into the String heap) 
&lt;LI&gt;&lt;EM&gt;Implementation&lt;/EM&gt; (an index into a File table, a AssemblyRef table, or null; more precisely, an Implementation coded index) &lt;/LI&gt;&lt;/UL&gt;&lt;/DIV&gt;
&lt;P&gt;There are some important points in the fine print at the end of section 22.24, which I'll reprint here:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;These rows in the ManifestResouce table are the result of &lt;SPAN class=inlinecode&gt;.mresource&lt;/SPAN&gt; directives 
&lt;LI&gt;The Offset specifies the byte offset within the referenced file at which this resource record begins; 
&lt;LI&gt;The &lt;EM&gt;Implementation&lt;/EM&gt; specifies which file holds this resource. It can be null or non-null: 
&lt;UL&gt;
&lt;LI&gt;if null, it means the resource is stored in the current file;&amp;nbsp; 
&lt;LI&gt;if not null, the resource is in another file. That whole file or part of that file can be resource. &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Based on the &lt;EM&gt;Implementation &lt;/EM&gt;value, we can split manifest resources into 2 categories: embedded or linked (in terms of C# compiler’s vocabulary). Check out part of C# compiler help message (via csc /?) and ILdasm output below; &lt;SPAN class=inlinecode&gt;foo.cs&lt;/SPAN&gt; is a simply C# file with only 1 Main method inside a class; &lt;SPAN class=inlinecode&gt;any.file&lt;/SPAN&gt; is a plain text file with a couple of characters inside. &lt;/P&gt;
&lt;DIV class=csharp&gt;/resource:&amp;lt;resinfo&amp;gt;&amp;nbsp; &lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; Embed the specified resource (Short form: /res)&lt;BR&gt;/linkresource:&amp;lt;resinfo&amp;gt; &lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; Link the specified resource to this assembly (Short form: /linkres)&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; Where the resinfo format is &amp;lt;file&amp;gt;[,&amp;lt;string name&amp;gt;[,public|private]]&amp;lt;/body&amp;gt;&lt;BR&gt;&lt;BR&gt;csc /out:embedded.exe /res:any.file,anyname,private foo.cs&lt;BR&gt;csc /out:linked.exe &amp;nbsp; /linkres:any.file,anyname,public foo.cs &lt;/DIV&gt;
&lt;DIV class=ilcode&gt;.mresource private anyname&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; // Offset: 0x00000000 Length: 0x0000000E&lt;BR&gt;}&lt;BR&gt;.module &lt;SPAN class=special&gt;embedded.exe&lt;/SPAN&gt; &lt;/DIV&gt;
&lt;DIV class=ilcode&gt;.file nometadata any.file&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; .hash = (C8 C5 4E 11 B1 CB 27 C3 37 6F A8 25 20 D5 3E F9 &amp;nbsp; // ..N...'.7o.% .&amp;gt;.&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; 93 2A 02 C0 ) &amp;nbsp; // .*..&lt;BR&gt;&lt;BR&gt;.mresource public anyname&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; .file any.file at 0x00000000&lt;BR&gt;}&lt;BR&gt;.module &lt;SPAN class=special&gt;linked.exe&lt;/SPAN&gt; &lt;/DIV&gt;
&lt;P&gt;From the ildasm output, we can guess the &lt;EM&gt;implementation&lt;/EM&gt; value of embedded.exe's &lt;SPAN class=inlinecode&gt;.mresource&lt;/SPAN&gt; is null; on the contrary, linked.exe's &lt;SPAN class=inlinecode&gt;.mresource&lt;/SPAN&gt; directive shows its manifest resource "anyname" is associated with &lt;SPAN class=inlinecode&gt;any.file&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;From another aspect, BCL provides several classes (such as ResourceManager) in the System.Resources namespace to help &lt;A href="http://msdn2.microsoft.com/en-us/library/f45fce5x(VS.80).aspx "&gt;create and manipulate resources&lt;/A&gt;; Reflection.Emit, as part of .NET library, is consistent. Different APIs are designed for the following 2 scenarios:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;the user does not have .resources file ready, and will emit each resource item one by one during the emit procedure;
&lt;LI&gt;the user has .resources file (created with ResourceWriter, or generated by resgen.exe) or any other format files (such as Crystal Report (.rpt), logo (.gif)) ready to integrate.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;To be consistent with the MSDN reflection emit documentation, I will call these 2 scenarios emitting "managed resource" and "resource blob" from now on.&lt;/P&gt;
&lt;P&gt;We now know that we have 2 approaches to integrate a resource into an assembly: embedded or linked; we also have 2 emit scenarios: emitting "managed resource" or "resource blob". These 4 combinations are all supported in .NET 2.0. Note in v1.x, we were unable to embed the "resource blob", which has been fixed by the newly added API &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.modulebuilder.definemanifestresource.aspx"&gt;ModuleBuilder.DefineManifestResource&lt;/A&gt;(a good doc, btw). &lt;/P&gt;
&lt;P&gt;The following list shows Reflection.Emit APIs to use for each combination: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Embed "&lt;/STRONG&gt;&lt;STRONG&gt;managed resource":&lt;/STRONG&gt; Get IResourceWriter fom &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.modulebuilder.defineresource.aspx"&gt;ModuleBuilder.DefineResource&lt;/A&gt;; follow with a series of IResourceWriter.AddResource or AddResourceData calls;
&lt;LI&gt;&lt;STRONG&gt;Embed "resource blob":&lt;/STRONG&gt; use &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.ModuleBuilder.DefineManifestResource.aspx"&gt;ModuleBuilder.DefineManifestResource&lt;/A&gt;;
&lt;LI&gt;&lt;STRONG&gt;Link "managed resource":&lt;/STRONG&gt; Get IResourceWriter from &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.AssemblyBuilder.DefineResource.aspx"&gt;AssemblyBuilder.DefineResource&lt;/A&gt;; follow with a series of IResourceWriter.AddResource or AddResourceData calls;
&lt;LI&gt;&lt;STRONG&gt;Link "resource blob":&lt;/STRONG&gt; use &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.AssemblyBuilder.AddResourceFile.aspx"&gt;AssemblyBuilder.AddResourceFile&lt;/A&gt;;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;If the .resources file is generated already, certainly we can use AssemblyBuilder.AddResouceFile to directly link it or ModuleBuilder.DefineManifestResource to embed it to the assembly being emitted.&lt;BR&gt;&lt;BR&gt;Attached you can find a sample code that I used to explore these APIs. After downloading the sample, you can take a look at the code and try compiling and running it. "temp.exe" is emitted with some resources; I suggest using Ildasm to check its Manifest. You can then run "temp.exe" to examine some resource information of its' own. I already see a couple of strange spots from the output ...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=584629" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/haibo_luo/attachment/584629.ashx" length="7076" type="text/plain" /><category domain="http://blogs.msdn.com/haibo_luo/archive/tags/Reflection.Emit/default.aspx">Reflection.Emit</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></channel></rss>