<?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</title><link>http://blogs.msdn.com/b/haibo_luo/</link><description /><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>ILVisualizer 2010 Solution</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2010/04/19/9998595.aspx</link><pubDate>Mon, 19 Apr 2010 17:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9998595</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=9998595</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2010/04/19/9998595.aspx#comments</comments><description>&lt;P&gt;The projects are set to be built against the .NET 4.0.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9998595" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-99-85-95/ILVisualizer2010.zip" length="53273" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/DynamicMethod/">DynamicMethod</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/VisualStudio/">VisualStudio</category></item><item><title>IronPython: System.Reflection.Assembly object</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/12/8177924.aspx</link><pubDate>Thu, 13 Mar 2008 06:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8177924</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=8177924</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/12/8177924.aspx#comments</comments><description>&lt;P&gt;IronPython offers a little bit more love to the &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.aspx"&gt;Assembly&lt;/A&gt; object instance: we can directly access the assembly's top-level members (namespace, public type) via the dot operation. System.Reflection provides many ways to let you hold the assembly object, such as Assembly.Load method, Type.Assembly property, ... 
&lt;P&gt;For example, given assembly1.dll compiled from the C# file below, &lt;A href="http://docs.python.org/lib/built-in-funcs.html" mce_href="http://docs.python.org/lib/built-in-funcs.html"&gt;dir&lt;/A&gt;(a1) in the python below shows the class name "C2" and the top level namespace "NS1" in its' dictionary. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// assembly1.cs
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;namespace &lt;/SPAN&gt;NS1 {
    &lt;SPAN style="COLOR: blue"&gt;namespace &lt;/SPAN&gt;NS2 {
        &lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;C1 &lt;/SPAN&gt;{ }
    }
}
&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;C2 &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;C3 &lt;/SPAN&gt;{ }
}
&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;C4 &lt;/SPAN&gt;{ }&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;# part 1 from file/test1.py
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;import &lt;/SPAN&gt;System
a1 = System.Reflection.Assembly.Load(&lt;SPAN style="COLOR: maroon"&gt;"assembly1"&lt;/SPAN&gt;)

&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;dir(a1)  &lt;SPAN style="COLOR: green"&gt;# ['C2', ..., 'NS1', ...]
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a1.NS1   &lt;SPAN style="COLOR: green"&gt;# &amp;lt;module 'NS1' (CLS module from assembly1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null)&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a1.C2    &lt;SPAN style="COLOR: green"&gt;# &amp;lt;type 'C2'&amp;gt;

# access non-public type
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a1.C4    &lt;SPAN style="COLOR: green"&gt;# AttributeError: 'Assembly' object has no attribute 'C4'

# access the down-level namespace, type with the dot operations
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a1.NS1.NS2.C1         &lt;SPAN style="COLOR: green"&gt;# &amp;lt;type 'C1'&amp;gt;
# access the nested type
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a1.C2.C3              &lt;SPAN style="COLOR: green"&gt;# &amp;lt;type 'C3'&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Normally I would use &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2007/09/25/5130072.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2007/09/25/5130072.aspx"&gt;clr.AddReference&lt;/A&gt; to bring in the CLR assembly. The python code below gives the similar output. &lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;# part 1 of file/test2.py
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;import &lt;/SPAN&gt;clr
clr.AddReference(&lt;SPAN style="COLOR: maroon"&gt;"assembly1"&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: blue"&gt;import &lt;/SPAN&gt;NS1 
&lt;SPAN style="COLOR: blue"&gt;import &lt;/SPAN&gt;C2

&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;NS1        &lt;SPAN style="COLOR: green"&gt;# &amp;lt;module 'NS1' (CLS module from assembly1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null)&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;C2         &lt;SPAN style="COLOR: green"&gt;# &amp;lt;type 'C2'&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;NS1.NS2    &lt;SPAN style="COLOR: green"&gt;# &amp;lt;module 'NS2' (CLS module from assembly1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null)&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;NS1.NS2.C1 &lt;SPAN style="COLOR: green"&gt;# &amp;lt;type 'C1'&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;C2.C3      &lt;SPAN style="COLOR: green"&gt;# &amp;lt;type 'C3'&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;However the first approach may help keep the global (and local) dictionary less "polluted" and &lt;EM&gt;sometimes&lt;/EM&gt; can be used to avoid the namespace/type name collision. For example, suppose we need to load in another assembly built from the following C# code, and we use the clr.AddReference approach.&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// assembly2.cs
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;namespace &lt;/SPAN&gt;NS1 { 
    &lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NS2 &lt;/SPAN&gt;{ } 
}&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;# part 2 of file/test2.py
&lt;/SPAN&gt;clr.AddReference(&lt;SPAN style="COLOR: maroon"&gt;"assembly2"&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;NS1.NS2    &lt;SPAN style="COLOR: green"&gt;# &amp;lt;type 'NS2'&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;NS1.NS2.C1 &lt;SPAN style="COLOR: green"&gt;# AttributeError: 'type' object has no attribute 'C1'
&lt;/SPAN&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;NS2 is a type now (no longer the namespace (or python module) NS1.NS2 from "assembly1"), and we lost the access to the type NS1.NS2.C1. If we use the assembly object approach, we can hold both the namespace NS1.NS2 from assembly1 and the type NS1.NS2 from assembly2; basically we can think the assembly variable name adds one more layer to prevent the name collision. Or in the other direction of thinking, what clr.AddReference does for you (related to implicit name merge/override) may not be what exactly you want.&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;# part 2 from file/test1.py
&lt;/SPAN&gt;a2 = System.Reflection.Assembly.Load(&lt;SPAN style="COLOR: maroon"&gt;"assembly2"&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a2.NS1     &lt;SPAN style="COLOR: green"&gt;# &amp;lt;module 'NS1' (CLS module from assembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null)&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a2.NS1.NS2 &lt;SPAN style="COLOR: green"&gt;# &amp;lt;type 'NS2'&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a1.NS1     &lt;SPAN style="COLOR: green"&gt;# &amp;lt;module 'NS1' (CLS module from assembly1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null)&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;a1.NS1.NS2 &lt;SPAN style="COLOR: green"&gt;# &amp;lt;module 'NS2' (CLS module from assembly1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null)&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Note that such name collision should rarely happen for well-designed framework assemblies. Also IronPython merge types/down-level namespaces under the same namespaces, even if they are from different assemblies. One simple example is System.Int32 from mscorlib.dll and System.Uri from System.dll, both peacefully under the "System" module.&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;import &lt;/SPAN&gt;System
&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;System            
&lt;SPAN style="COLOR: green"&gt;# &amp;lt;module 'System' (CLS module, 2 assemblies loaded)&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;System.__file__   
&lt;SPAN style="COLOR: green"&gt;# ['mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089', 
#  'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089']
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;import &lt;/SPAN&gt;clr
&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;clr.GetClrType(System.Int32).Assembly  
&lt;SPAN style="COLOR: green"&gt;# &amp;lt;Assembly mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;print &lt;/SPAN&gt;clr.GetClrType(System.Uri).Assembly    
&lt;SPAN style="COLOR: green"&gt;# &amp;lt;Assembly System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8177924" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>IronPython: System.Array</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/12/8177915.aspx</link><pubDate>Thu, 13 Mar 2008 06:04:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8177915</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=8177915</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/12/8177915.aspx#comments</comments><description>&lt;p&gt;When you start interop'ing with .NET in IronPython, sooner or later, you will find that you are in need of creating an array as argument. There are mainly 2 ways to create array objects: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Array with type indexing (for one-dimensional array object only), and  &lt;li&gt;classic reflection API: Array.CreateInstance &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;System.Array indexing with a type creates a concrete array type, which can then take a collection of the element objects (or an enumerable) and form the array object. There are half dozen &lt;a href="http://msdn2.microsoft.com/en-us/library/system.array.createinstance.aspx"&gt;Array.CreateInstance&lt;/a&gt; overloads, which allow us to create one-dimensional empty array, also multi-dimensional/non-zero lower-bound arrays. &lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;import &lt;/span&gt;System
array_int = System.Array[int]
&lt;span style="color: blue"&gt;print &lt;/span&gt;array_int               &lt;span style="color: green"&gt;# &amp;lt;type 'Array[int]'&amp;gt;

# list
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;array_int([1, 2])       &lt;span style="color: green"&gt;# System.Int32[](1, 2)
# tuple
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;array_int((3, 4, 5))    &lt;span style="color: green"&gt;# System.Int32[](3, 4, 5)
# xrange
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;array_int(xrange(6,10)) &lt;span style="color: green"&gt;# System.Int32[](6, 7, 8, 9)
# CLR List
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;array_int(System.Collections.Generic.List[int]()) &lt;span style="color: green"&gt;# System.Int32[]()

# one-dimensional array 
&lt;/span&gt;a1 = System.Array.CreateInstance(int, 5)
&lt;span style="color: blue"&gt;for &lt;/span&gt;i &lt;span style="color: blue"&gt;in &lt;/span&gt;range(5): a1[i] = i * 10
&lt;span style="color: blue"&gt;print &lt;/span&gt;a1        &lt;span style="color: green"&gt;# System.Int32[](0, 10, 20, 30, 40)

# two-dimensional array 
&lt;/span&gt;a2 = System.Array.CreateInstance(float, 2, 2)
a2[1, 1] = 3.14
&lt;span style="color: blue"&gt;print &lt;/span&gt;a2        &lt;span style="color: green"&gt;# System.Double[,](
                # 0.0, 0.0
                # 0.0, 3.14)&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;IronPython also supports some python list-like operation to the CLR array objects, such as indexing with slice, +, *, in...&lt;/p&gt;&lt;pre class="code"&gt;a1 = array_int(range(5))
a2 = array_int([100])

&lt;span style="color: green"&gt;# slice
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;a1[1:-1]      &lt;span style="color: green"&gt;# System.Int32[](1, 2, 3)
# +
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;a1 + a2       &lt;span style="color: green"&gt;# System.Int32[](0, 1, 2, 3, 4, 100)
# *
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;a1 * 2        &lt;span style="color: green"&gt;# System.Int32[](0, 1, 2, 3, 4, 0, 1, 2, 3, 4)
# +, upcast the result to object[]
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;a2 + System.Array[str](&lt;span style="color: maroon"&gt;'py'&lt;/span&gt;)  &lt;span style="color: green"&gt;# System.Object[](100, 'p', 'y')

# slice with step
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;a1[1::2]      &lt;span style="color: green"&gt;# System.Int32[](1, 3)
# assignment 
&lt;/span&gt;a1[1::2] = [11, 13]
&lt;span style="color: blue"&gt;print &lt;/span&gt;a1            &lt;span style="color: green"&gt;# System.Int32[](0, 11, 2, 13, 4)

# in/__contains__
&lt;/span&gt;&lt;span style="color: blue"&gt;print &lt;/span&gt;11 &lt;span style="color: blue"&gt;in &lt;/span&gt;a1      &lt;span style="color: green"&gt;# True
&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8177915" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>IronPython: ipyw.exe</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/12/8177907.aspx</link><pubDate>Thu, 13 Mar 2008 06:03:48 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8177907</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=8177907</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/12/8177907.aspx#comments</comments><description>&lt;p&gt;Each IronPython binary release ships two executable files: ipy.exe and ipyw.exe. Their (only) difference is, ipy.exe is a console application and ipyw.exe is a windows application. So given the following winform.py, &lt;pre class="code"&gt;&lt;span style="color: green"&gt;## winform.py
&lt;/span&gt;&lt;span style="color: blue"&gt;import &lt;/span&gt;clr
clr.AddReference(&lt;span style="color: maroon"&gt;"System.Windows.Forms"&lt;/span&gt;)
&lt;span style="color: blue"&gt;from &lt;/span&gt;System.Windows.Forms &lt;span style="color: blue"&gt;import &lt;/span&gt;*

&lt;span style="color: blue"&gt;class &lt;/span&gt;SimpleForm(Form):
    &lt;span style="color: blue"&gt;def &lt;/span&gt;__init__(self):
        self.Text = &lt;span style="color: maroon"&gt;'Simple Winform'

&lt;/span&gt;Application.Run(SimpleForm())
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Running it with ipy.exe will keep the associated console; however, if I launch it with ipyw.exe in a console window, I can continue working on other stuffs within that console. 
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/IronPythonipyw.exe_1377C/ipy.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" border="0" alt="ipy" align="left" src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/IronPythonipyw.exe_1377C/ipy_thumb.png" width="369" height="226"&gt;&lt;/a&gt; 
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/IronPythonipyw.exe_1377C/ipyw_1.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" border="0" alt="ipyw" src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/IronPythonipyw.exe_1377C/ipyw_thumb_1.png" width="357" height="232"&gt;&lt;/a&gt; 
&lt;p&gt;I found that Shawn wrote some background about WINDOW_CUI/WINDOW_GUI subsystem &lt;a href="http://blogs.msdn.com/shawnfa/archive/2005/06/06/425804.aspx"&gt;here&lt;/a&gt;. 
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8177907" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>SignatureResolver (unfinished)</title><link>http://blogs.msdn.com/b/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 - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=8115220</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/08/8115220.aspx#comments</comments><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/cfs-file.ashx/__key/communityserver-components-postattachments/00-08-11-52-20/SignatureResolver2008.zip" length="7963" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/Reflection/">Reflection</category></item><item><title>ILVisualizer VS2008 solution</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/07/8107924.aspx</link><pubDate>Sat, 08 Mar 2008 03:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8107924</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=8107924</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2008/03/07/8107924.aspx#comments</comments><description>&lt;P&gt;I attached the ILVisualizer VS2008 solution in this post. There is no source code update; the only change is to upgrade the Microsoft.VisualStudio.DebuggerVisualizers.dll reference from version 8.0.0.0 to version 9.0.0.0. &lt;/P&gt;
&lt;P&gt;Just for your convenience, so you can see a successful build after downloading in VS2008.&lt;/P&gt;
&lt;P&gt;Thanks Julien for leaving the &lt;A class="" target=_blank&gt;instruction&lt;/A&gt;&amp;nbsp;&lt;A class="" href="http://blogs.msdn.com/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx#4555501" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx#4555501"&gt;here&lt;/A&gt;. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8107924" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-08-10-79-24/ILVisualizer2008.zip" length="49179" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/VisualStudio/">VisualStudio</category></item><item><title>IronPython: Accessing the .NET Field</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/28/5753681.aspx</link><pubDate>Mon, 29 Oct 2007 06:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5753681</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5753681</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/28/5753681.aspx#comments</comments><description>&lt;p&gt;The .NET libraries normally do not expose the public field, but we can still find its' presence for certain scenarios. IronPython treats the .NET fields like python attribute. For python attribute, the typical operations are set, get and delete. In general, IronPython throws TypeError when deleting members of CLR types and their objects (so for fields). To do set and get operation, the IronPython code looks similar to C# code. Updating (setting) values to the read-only or literal fields throws as we expect.&lt;br&gt;&lt;/p&gt; &lt;div class="csharp"&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;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public static int&lt;/span&gt; StaticField;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public int&lt;/span&gt; InstanceField;&lt;br&gt;} &lt;/div&gt; &lt;div class="csharp"&gt;&amp;gt;&amp;gt;&amp;gt; ...&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;C.StaticField = 1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # set&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;C.StaticField&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # get&lt;br&gt;1&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;c = C()&lt;/span&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;c.InstanceField = 2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # set&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;c.InstanceField&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # get&lt;br&gt;2&lt;br&gt;&lt;/div&gt; &lt;p&gt;Guess what you will get for C.InstanceField? It is "field descriptor", same as C.__dict__['InstanceField'], upon which we can call __set__/__get__ or two equivalent helper methods SetValue/GetValue (feel like repeating CLR reflection FieldInfo API here). Although not shown below, we can also set/get the value of the static field too by calling these methods on C.__dict__['StaticField']. &lt;/p&gt; &lt;div class="csharp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;C.InstanceField&lt;/span&gt;&lt;br&gt;&amp;lt;field# InstanceField on C&amp;gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;C.InstanceField is C.__dict__['InstanceField']&lt;/span&gt;&lt;br&gt;True&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;C.InstanceField.__set__(c, 3)&lt;/span&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;C.InstanceField.__get__(c)&lt;/span&gt;&lt;br&gt;3&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;C.InstanceField.SetValue(c, 4)&lt;/span&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;C.InstanceField.GetValue(c)&lt;/span&gt;&lt;br&gt;4 &lt;/div&gt; &lt;p&gt;IronPython allows accessing static field on instance too. On the other hand, C# compiler requires type name to access static member (otherwise &lt;a href="http://msdn2.microsoft.com/en-us/library/zhcxt2bd%28vs.71%29.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/zhcxt2bd(vs.71).aspx"&gt;CS0176&lt;/a&gt;). &lt;/p&gt; &lt;div class="csharp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;c.StaticField = 5&lt;/span&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;c.StaticField, C.StaticField&lt;/span&gt;&lt;br&gt;(5, 5)&lt;br&gt;&lt;/div&gt; &lt;p&gt;Updating fields of &lt;i&gt;value types&lt;/i&gt; is not allowed. If interested, you may go ahead read the design decision &lt;a href="http://channel9.msdn.com/wiki/default.aspx/IronPython.ValueTypes" mce_href="http://channel9.msdn.com/wiki/default.aspx/IronPython.ValueTypes"&gt;here&lt;/a&gt;. Until recently I did not know that as a remedy, the feature of &lt;a href="http://blogs.msdn.com/haibo_luo/archive/2007/10/02/5246577.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2007/10/02/5246577.aspx"&gt;setting fields/properties in the constructor call&lt;/a&gt; should be able to set field for value types while still keeping value types effectively immutable after the creation. Unfortunately we had no tests to cover this part (which never worked). This code below illustrates the expected behavior. I expect it to work soon.&lt;br&gt;&lt;/p&gt; &lt;div class="csharp"&gt;&lt;span class="cskeyword"&gt;public struct &lt;/span&gt;&lt;span class="cstype"&gt;MyPoint &lt;/span&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public int&lt;/span&gt; X, Y;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public override string&lt;/span&gt; ToString() { &lt;span class="cskeyword"&gt;return string&lt;/span&gt;.Format(&lt;span class="csstring"&gt;"X: {0}, Y: {1}"&lt;/span&gt;, X, Y); }&lt;br&gt;} &lt;/div&gt; &lt;div class="csharp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;p = MyPoint(X=1, Y=2)&lt;/span&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;p&lt;/span&gt; &lt;br&gt;&amp;lt;MyPoint object at 0x000000000000002C [&lt;span class="special"&gt;X: 1, Y: 2&lt;/span&gt;]&amp;gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;p.X = 3&lt;/span&gt;&lt;br&gt;# one kind of exception still throws&lt;br&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5753681" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>VisualStudio as my IronPython editor</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/16/5482940.aspx</link><pubDate>Wed, 17 Oct 2007 08:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5482940</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5482940</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/16/5482940.aspx#comments</comments><description>&lt;P&gt;The following steps are what I did to get Visual Studio ready as my IronPython (and IronRuby) editor.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Install the latest internal dogfood build of Visual Studio 2008. 
&lt;UL&gt;
&lt;LI&gt;you may use Visual Studio 2005 or download the &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=B98A61BA-99B0-40B7-AB6E-5386A2B94217&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyId=B98A61BA-99B0-40B7-AB6E-5386A2B94217&amp;amp;displaylang=en"&gt;VS 2008 public beta2&lt;/A&gt;;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Download and install &lt;A href="http://www.microsoft.com/downloads/details.aspx?familyid=A5189BCB-EF81-4C12-9733-E294D13A58E6&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?familyid=A5189BCB-EF81-4C12-9733-E294D13A58E6&amp;amp;displaylang=en"&gt;ASP.NET futures release (July 2007)&lt;/A&gt;. This will give me the nice syntax coloring and (well... limited) intellisense for python code. 
&lt;UL&gt;
&lt;LI&gt;you may download &lt;A href="http://www.microsoft.com/downloads/details.aspx?familyid=d9000e2c-bd3f-4717-a181-723960814e16&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?familyid=d9000e2c-bd3f-4717-a181-723960814e16&amp;amp;displaylang=en"&gt;VSSDK 2008 CTP&lt;/A&gt;, and build the IronPython integration sample, which will give you the similar editing experience;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Download the attached add-in binary zip (poorly named as DlrToolsAddin); for my Vista box, I extract them under "%USERPROFILE%\Documents\Visual Studio 2008\Addins". I wrote this add-in basically to allow me to run the script inside the Visual Studio, and show the output in the output window. 
&lt;UL&gt;
&lt;LI&gt;if you consider using it for VS 2005, you will need put it in "Visual Studio 2005\Addins".&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Say, I am trying the example in my previous post, I create a new C# file (sample.cs) without creating solution/project, I can press Ctrl+1 (or the first button in the DlrTools toobar)&amp;nbsp; to get it compiled to sample.dll in the local directory. You see the compile result at the bottom output window. Then I create a python file (method.py) in the same directory, type in some code (shown in color). Again, I can press Ctrl+1, the result are shown in the output window. I do not need leave VS and run these files in the cmd.exe window.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/DlrToolsAddin_8432/image_16.png" mce_href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/DlrToolsAddin_8432/image_16.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=529 alt=image src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/DlrToolsAddin_8432/image_thumb_7.png" width=697 border=0 mce_src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/DlrToolsAddin_8432/image_thumb_7.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;A href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/DlrToolsAddin_8432/image_14.png" mce_href="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/DlrToolsAddin_8432/image_14.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=526 alt=image src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/DlrToolsAddin_8432/image_thumb_6.png" width=693 border=0 mce_src="http://blogs.msdn.com/blogfiles/haibo_luo/WindowsLiveWriter/DlrToolsAddin_8432/image_thumb_6.png"&gt;&lt;/A&gt;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Sometimes I want to run the same code with different tools (for example, to check IronPython compatibility, I often run the same .py file against C-Python 2.5 too). That is the first combo box comes to play. &lt;/P&gt;
&lt;P&gt;The second combo box is to set the working directory: "." means the current directory where the active file lives, ".." for the parent directory of the current file, or you may use the absolute path. Such support is needed to run C-Python regression tests. (For the add-in implementation side, I feel what I really want is a combo box of type vsCommandControlTypeDynamicCombo, which seems not available for add-in development).&lt;/P&gt;
&lt;P&gt;The delete button is to remove your tool choice for those files you pressed "Run Script". By clicking the last button, an XML file (specifying which tools for which file extension) is opened so you may change it. &lt;STRONG&gt;You must update it with your tool paths&lt;/STRONG&gt;, since the default setting is suited for myself. &lt;/P&gt;
&lt;P&gt;You may also run part of the file by selecting those lines first (A temporary file is created and will be deleted after VS shutdown). &lt;/P&gt;
&lt;P&gt;One bad thing I noticed of this add-in is that sometimes I press the "run script" button to start debugging, both icons have similar shapes.&lt;/P&gt;
&lt;P&gt;To uninstall it, delete DlrToolsAddin.* files under "Addins"; and then run once "devenv.exe /resetaddin DlrToolsAddin.Connect".&lt;/P&gt;
&lt;P&gt;The source code (VS2008 project) is also attached. &lt;EM&gt;Disclaimer: THE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES INTENDED OR IMPLIED. USE AT YOUR OWN RISK. &lt;/EM&gt;Hope you like Visual Studio as your IronPython editor.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5482940" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-05-48-29-40/DlrToolsAddin.zip" length="34131" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronRuby/">IronRuby</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/VisualStudio/">VisualStudio</category></item><item><title>IronPython: explicitly choose one method</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/11/5413239.aspx</link><pubDate>Fri, 12 Oct 2007 06:32:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5413239</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5413239</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/11/5413239.aspx#comments</comments><description>&lt;p&gt;C# allows method overloading. Given an argument list, the compiler performs the overload resolution to select the best method to invoke. The chosen method token is baked into the assembly. IronPython does the method resolution at the IronPython &lt;em&gt;run time&lt;/em&gt;; for most scenarios, it has no problem in picking up the most reasonable one based on the argument list. The rules are a bit complicated, and I will leave them for a future post. If you believe IronPython chooses the "unexpected" method for your scenario, please do let us know.&lt;/p&gt; &lt;p&gt;IronPython also provides the "Overloads" (python) attribute for the bound method, on which we can do index operation with parameter types to get the exact method we want. In the example below, the .NET reflection API &lt;a href="http://msdn2.microsoft.com/en-us/library/system.type.makebyreftype.aspx"&gt;Type.MakeByRefType&lt;/a&gt; and &lt;a href="http://msdn2.microsoft.com/en-us/library/system.type.makearraytype.aspx"&gt;MakeArrayType&lt;/a&gt; are used in order to get those constructed types. Since these calls are only available for System.Type object, clr.GetClrType is called first on the python type to get the underlying CLR type. However, I am able to use the python type for the first 2 index calls (thanks to the type conversion).&lt;/p&gt; &lt;p class="csharp"&gt;&lt;span class="cskeyword"&gt;public class&lt;/span&gt; &lt;span class="cstype"&gt;ChooseOverload &lt;/span&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M(&lt;span class="cskeyword"&gt;int &lt;/span&gt;arg) { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(1); }&lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M(&lt;span class="cskeyword"&gt;byte &lt;/span&gt;arg1, &lt;span class="cskeyword"&gt;byte &lt;/span&gt;arg2) { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(2); }&lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M(&lt;span class="cskeyword"&gt;ref int&lt;/span&gt; arg) { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(3); arg = 10; }&lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M(&lt;span class="cskeyword"&gt;int&lt;/span&gt;[] arg) { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(4); }&lt;br&gt;}&lt;/p&gt; &lt;p class="csharp"&gt;&amp;gt;&amp;gt;&amp;gt; ... # add the assembly&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;import ChooseOverload&lt;/span&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o = ChooseOverload()&lt;/span&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M&lt;/span&gt;&lt;br&gt;&amp;lt;built-in method M of ChooseOverload object at 0x000000000000002B&amp;gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M.Overloads&lt;/span&gt;&lt;br&gt;{'M(self, int arg)': &amp;lt;built-in function M&amp;gt;, 'M(self, Byte arg1, Byte arg2)': &amp;lt;built-in function M&amp;gt;, 'int M(self, int arg)': &amp;lt;built-in function M&amp;gt;, 'M(self, Array[int] arg)': &amp;lt;built-in function M&amp;gt;}&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M.Overloads[int](1)&lt;/span&gt;&lt;br&gt;1&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M.Overloads[System.Byte, System.Byte](1, 2)&lt;/span&gt;&lt;br&gt;2&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M.Overloads[clr.GetClrType(int).MakeByRefType()](1)&lt;/span&gt;&lt;br&gt;3&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M.Overloads[clr.GetClrType(int).MakeArrayType()](None)&lt;/span&gt;&lt;br&gt;4&lt;br&gt;&lt;/p&gt; &lt;p class="style1"&gt;When generics come to the picture, o.M could mean the generic method. &lt;a href="http://blogs.msdn.com/haibo_luo/archive/2007/09/25/5130087.aspx"&gt;Similar to the generic type&lt;/a&gt;, IronPython chooses the index operation to hold the instantiated generic method. Currently IronPython has no support to specify parameter types which are (or made from) generic type parameters (of either the generic method or type). Expect this will be supported one day.&lt;/p&gt; &lt;p class="csharp"&gt;&amp;nbsp;&lt;span class="cskeyword"&gt;public void&lt;/span&gt; M2&amp;lt;T&amp;gt;(T arg)&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(5); }&lt;br&gt;&amp;nbsp;&lt;span class="cskeyword"&gt;public void&lt;/span&gt; M2&amp;lt;T&amp;gt;(&lt;span class="cskeyword"&gt;byte &lt;/span&gt;arg) { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(6); }&lt;/p&gt; &lt;p class="csharp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M2[int](1)&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # bind to the first M2 given the argument "1"&lt;br&gt;5&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M2[int].Overloads[System.Byte](1)&amp;nbsp; &lt;/span&gt;# in order to get the second M2&lt;br&gt;6 &lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="typein"&gt;o.M2[int].Overloads[???](1)&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # unable to pick the first M2 currently &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5413239" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>IronPython: Provide (or not) Argument for by-ref Parameter</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/04/5284947.aspx</link><pubDate>Fri, 05 Oct 2007 08:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5284947</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5284947</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/04/5284947.aspx#comments</comments><description>&lt;P&gt;Python function may return multiple objects as a tuple. The .NET method can only return one object as the result of a call; in order to return more than one objects, by-ref parameters are needed. They are decorated with the &lt;A href="http://msdn2.microsoft.com/en-us/library/aa645761(VS.71).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa645761(VS.71).aspx"&gt;parameter modifier&lt;/A&gt; (ref, out) in C#.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/zkw5c9ak.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/zkw5c9ak.aspx"&gt;Dictionary.TryGetValue&lt;/A&gt;(TKey key, out TValue value) has an &lt;A href="http://msdn2.microsoft.com/en-us/library/aa645764(VS.71).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa645764(VS.71).aspx"&gt;output parameter&lt;/A&gt; "value". The API returns true if the dictionary contains an element with the specified key (the element value itself is returned to the parameter "value"), otherwise it returns false. When making calls to such methods in IronPython, we may not pass in argument for the output parameter. Instead, the result of such .NET method call in IronPython will likely be a tuple (unless the .NET method's return type is void and the method has only one by-ref parameter), which contains the value of the output parameter (see the example below). &lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;import&lt;/SPAN&gt; System&lt;BR&gt;d = System.Collections.Generic.Dictionary[int, str]()&lt;BR&gt;d[1], d[2] = &lt;SPAN class=csstring&gt;'One'&lt;/SPAN&gt;, &lt;SPAN class=csstring&gt;'Two'&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;d.TryGetValue(1) &lt;SPAN class=cscomment&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # (True, 'One')&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;d.TryGetValue(2)[1]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cscomment&gt;# Two&lt;/SPAN&gt;&amp;nbsp; &lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;d.TryGetValue(3)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cscomment&gt;# (False, None)&lt;/SPAN&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;We may also pass a clr.Reference object for the output parameter. The clr.Reference object has only one member "Value", which will carry the output parameter value after the call. "clr.Reference" object is of the type identical to System.Runtime.CompilerServices.StrongBox&amp;lt;T&amp;gt; in the new .NET Framework 3.5. When encountering this type of argument, IronPython codegen/runtime does something special to update the "Value".&lt;/P&gt;
&lt;DIV class=csharp&gt;x = clr.Reference[str]()&amp;nbsp;&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=cscomment&gt;# like "new StrongBox&amp;lt;string&amp;gt;()" in C#&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;d.TryGetValue(1, x), x.Value&amp;nbsp;&amp;nbsp; &lt;SPAN class=cscomment&gt;# True One&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;d.TryGetValue(3, x), x.Value&amp;nbsp;&amp;nbsp; &lt;SPAN class=cscomment&gt;# False None&lt;/SPAN&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;For &lt;A href="http://msdn2.microsoft.com/en-us/library/aa645763(VS.71).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa645763(VS.71).aspx"&gt;reference parameter&lt;/A&gt;, we are required to pass in something. If the argument is not clr.Reference object, such reference argument value will also be part of the returned tuple; otherwise, the by-ref change is tracked inside clr.Reference. The following C# code is my twisted way to find the maximum number; the IronPython snippet shows the behaviors of calling that method not using and using clr.Reference.&lt;/P&gt;
&lt;DIV class=csharp&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 bool&lt;/SPAN&gt; M(&lt;SPAN class=cskeyword&gt;int &lt;/SPAN&gt;current, &lt;SPAN class=cskeyword&gt;ref int&lt;/SPAN&gt; max) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;if &lt;/SPAN&gt;(current &amp;gt; max) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; max = current; &lt;SPAN class=cskeyword&gt;return &lt;/SPAN&gt;true;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;SPAN class=cskeyword&gt;else&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;return &lt;/SPAN&gt;false;&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;import &lt;/SPAN&gt;C&lt;BR&gt;o = C()&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;o.M(10, 20)&amp;nbsp;&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=cscomment&gt;# (False, 20)&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;o.M(30, 20)&amp;nbsp;&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=cscomment&gt;# (True, 30)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&lt;BR&gt;x = clr.Reference[int](20)&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;o.M(10, x), x&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=cscomment&gt;# False 20&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;o.M(30, x), x&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=cscomment&gt;# True 30&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&lt;BR&gt;o.M(1)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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=cscomment&gt;# TypeError: M() takes exactly 2 arguments (1 given)&lt;/SPAN&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Note if the .NET method contains more than one by-ref parameters, IronPython expects the user to provide proper clr.Reference objects for either ALL or NONE of them. A mix of clr.Reference object and normal argument/omission (for out parameter) will cause error (as illustrated below).&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;public int&lt;/SPAN&gt; M2(&lt;SPAN class=cskeyword&gt;ref int&lt;/SPAN&gt; x, &lt;SPAN class=cskeyword&gt;ref int&lt;/SPAN&gt; y) {...}&lt;/DIV&gt;
&lt;DIV class=csharp&gt;o.M2(clr.Reference[int](1), 2) &lt;SPAN class=cscomment&gt;# TypeError&lt;/SPAN&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5284947" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>IronPython: Keyword Argument to Set .NET Property/Field</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/02/5246577.aspx</link><pubDate>Tue, 02 Oct 2007 22:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5246577</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5246577</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/02/5246577.aspx#comments</comments><description>&lt;P&gt;Use keyword arguments to set properties or fields… you likely ask the question: where can we do this? IronPython allows it in the constructor call, the call against the .NET type. Such keyword should be the name of public field, or property (which is not read-only). After creating the object instance, each keyword argument value is then set to the corresponding field or property. Note keyword arguments can be used for the constructor parameters as usual.&lt;/P&gt;
&lt;P&gt;The IronPython code below is to monitor any python file change under the directory "C:\temp". I used this special argument passing in the 2nd line.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;import &lt;/SPAN&gt;System &lt;BR&gt;fsw = System.IO.FileSystemWatcher(&lt;SPAN class=csstring&gt;r"C:\temp"&lt;/SPAN&gt;, &lt;B&gt;Filter=&lt;/B&gt;&lt;SPAN class=style1&gt;"*.py"&lt;/SPAN&gt;&lt;B&gt;, IncludeSubdirectories = True, EnableRaisingEvents = True&lt;/B&gt;)&lt;BR&gt;&lt;SPAN class=cskeyword&gt;def &lt;/SPAN&gt;on_changed(o,e): &lt;SPAN class=cskeyword&gt;print &lt;/SPAN&gt;e.ChangeType, e.FullPath&lt;BR&gt;fsw.Changed += on_changed&lt;BR&gt;&lt;BR&gt;System.Console.ReadLine()&lt;/DIV&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx"&gt;FileSystemWatcher&lt;/A&gt; has three constructors (see below). The code uses the second one (not the third one)."c:\temp" is positional argument for "path"; the next 3 keywords arguments are transformed to the property (Filter/IncludeSubdirectories/…) assignments after the object creation. &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;public FileSystemWatcher(); 
&lt;LI&gt;public FileSystemWatcher(string path); 
&lt;LI&gt;public FileSystemWatcher(string path, string filter); &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I am not going to argue whether this feature is good or bad. You may find it handy in some places. The user could get confused when the constructor parameter name is same as the field/property name (Although it is unlikely as most libraries are following the .NET framework guideline: property name starts with the capital character, while the parameter name does opposite). One of our summer interns also proposed to extend this feature to event setting as keyword argument. It is currently not supported, not sure whether it will ever come in the future.&lt;/P&gt;
&lt;P&gt;Note this code above actually doe not work in IronPython 2.0 alpha 4 (due to bugs). The upcoming &lt;A href="http://www.codeplex.com/IronPython/Release/ProjectReleases.aspx?ReleaseId=2573" target=_blank mce_href="http://www.codeplex.com/IronPython/Release/ProjectReleases.aspx?ReleaseId=2573"&gt;2.0 alpha5&lt;/A&gt; will have the fix. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5246577" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>IronPython: Passing Arguments for a Call</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/01/5230964.aspx</link><pubDate>Tue, 02 Oct 2007 02:06:41 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5230964</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5230964</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/10/01/5230964.aspx#comments</comments><description>&lt;p&gt;After getting a CLR type, we can play it like a python type. We can get the class/static methods using the dot operator ("attribute reference") on the type, or create an instance of it and then get the instance methods. In Python’s word, these methods are callable objects, and we can make "&lt;a href="http://docs.python.org/ref/calls.html"&gt;calls&lt;/a&gt;" on them using the call operator ("()"). I will write about the method call in the next couple of posts, this one is about passing arguments for calls in IronPython.&lt;/p&gt; &lt;p&gt;Python &lt;a href="http://docs.python.org/ref/function.html#function"&gt;function definition&lt;/a&gt; allows several different &lt;i&gt;parameter&lt;/i&gt; styles: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;parameter which accepts excess positional arguments,  &lt;li&gt;parameter with default value,  &lt;li&gt;parameter which accepts excess keyword arguments. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Here are some examples showing the common parameter style, and each of 3 styles listed above. &lt;/p&gt; &lt;div class="csharp"&gt;&lt;span class="cskeyword"&gt;def &lt;/span&gt;f1(x, y):&amp;nbsp;&amp;nbsp; &lt;span class="cskeyword"&gt;print &lt;/span&gt;x, y&lt;br&gt;&lt;span class="cskeyword"&gt;def &lt;/span&gt;f2(x, *y):&amp;nbsp; &lt;span class="cskeyword"&gt;print &lt;/span&gt;x, len(y)&lt;br&gt;&lt;span class="cskeyword"&gt;def &lt;/span&gt;f3(x, y=5): &lt;span class="cskeyword"&gt;print &lt;/span&gt;x, y&lt;br&gt;&lt;span class="cskeyword"&gt;def &lt;/span&gt;f4(x, **y): &lt;span class="cskeyword"&gt;print &lt;/span&gt;x, y&lt;/div&gt; &lt;p&gt;When making calls (on these functions), Python allows many different &lt;i&gt;argument&lt;/i&gt; styles too. The following type (in C#) defines some methods, each with interesting &lt;i&gt;parameter&lt;/i&gt; list.&lt;/p&gt; &lt;div class="csharp"&gt;&lt;span class="cscomment"&gt;// sample.cs&lt;/span&gt;&lt;br&gt;&lt;span class="cskeyword"&gt;public class&lt;/span&gt; &lt;span class="cstype"&gt;ArgumentList &lt;/span&gt;&lt;br&gt;&amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M1(&lt;span class="cskeyword"&gt;int &lt;/span&gt;x, &lt;span class="cskeyword"&gt;int &lt;/span&gt;y) { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(&lt;span class="csstring"&gt;"{0} {1}"&lt;/span&gt;, x, y); }&lt;br&gt;&amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M2(&lt;span class="cskeyword"&gt;int &lt;/span&gt;x, &lt;span class="cskeyword"&gt;params int&lt;/span&gt;[] y) { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(&lt;span class="csstring"&gt;"{0} {1}"&lt;/span&gt;, x, y.Length); }&lt;br&gt;&amp;nbsp; &lt;span class="cskeyword"&gt;public void&lt;/span&gt; M3(&lt;span class="cskeyword"&gt;int &lt;/span&gt;x, [&lt;span class="cstype"&gt;DefaultParameterValue&lt;/span&gt;(5)] &lt;span class="cskeyword"&gt;int &lt;/span&gt;y) { &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(&lt;span class="csstring"&gt;"{0} {1}"&lt;/span&gt;, x, y); }&lt;br&gt;}&lt;/div&gt; &lt;p&gt;In terms of the parameter style, we will see that M1 is equivalent as pure python function f1, same for M2/f2, M3/f3 (I was unable to find similar parameter kind in C# for f4). When calling these .NET methods, IronPython supports all &lt;i&gt;argument&lt;/i&gt; styles as Python does. &lt;/p&gt; &lt;p&gt;M1 is the simplest in the parameter definition, but we can call it with different argument lists. Each call below prints "1, 2", same as if the python function "f1" is called. &lt;/p&gt; &lt;div class="csharp"&gt;&lt;span class="cskeyword"&gt;import &lt;/span&gt;clr&lt;br&gt;clr.AddReference(&lt;span class="csstring"&gt;"sample"&lt;/span&gt;)&lt;br&gt;&lt;br&gt;&lt;span class="cskeyword"&gt;import &lt;/span&gt;ArgumentList&lt;br&gt;o = ArgumentList()&lt;br&gt;f1 = o.M1&lt;br&gt;&lt;br&gt;f1(1, 2)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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="cscomment"&gt;# positional arguments&lt;/span&gt; &lt;br&gt;f1(1, y = 2)&amp;nbsp;&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="cscomment"&gt;# positional &amp;amp; keyword arguments&lt;/span&gt;&lt;br&gt;f1(y = 2, x = 1)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;# keyword arguments&lt;/span&gt;&lt;br&gt;f1(*(1, 2))&amp;nbsp;&amp;nbsp;&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="cscomment"&gt;# unpack the sequence as positional args&lt;/span&gt;&lt;br&gt;f1(1, *(2,))&amp;nbsp;&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="cscomment"&gt;# positional &amp;amp; unpack&lt;/span&gt;&lt;br&gt;f1(**{'x': 1, 'y': 2})&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;# unpack the dictionary as keyword args&lt;/span&gt;&lt;/div&gt; &lt;p&gt;C# parameter array (parameter with &lt;i&gt;"params", &lt;/i&gt;or exactly &lt;a href="http://msdn2.microsoft.com/en-us/library/system.paramarrayattribute.aspx"&gt;ParamArrayAttribute&lt;/a&gt;) is treated like "*y" in f2. The user are allowed to pass 0 or more arguments to the parameter "y".&lt;/p&gt; &lt;div class="csharp"&gt;f2 = o.M2&lt;br&gt;f2(1)&amp;nbsp;&amp;nbsp;&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="cscomment"&gt;# print: 1 0&lt;/span&gt;&lt;br&gt;f2(1, 2)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 1&lt;/span&gt;&lt;br&gt;f2(*(1, 2, 3))&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 2&lt;/span&gt;&lt;br&gt;f2(1, 2, 3, 4, 5)&amp;nbsp; &lt;span class="cscomment"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 4&lt;/span&gt;&lt;/div&gt; &lt;p&gt;The C# language does not have built-in support for the default value argument (IL does, with the .param directive inside the method body); even if the parameter is decorated with &lt;a href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.defaultparametervalueattribute.aspx"&gt;System.Runtime.InteropServices.DefaultParameterValueAttribute&lt;/a&gt;, C# calls on such methods still require argument passed in for that parameter. However IronPython (like Python) honors such default value parameters. &lt;/p&gt; &lt;div class="csharp"&gt;f3 = o.M3&lt;br&gt;f2(1)&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="cscomment"&gt;# print: 1 5&lt;/span&gt;&lt;br&gt;f2(x = 1)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 5&lt;/span&gt;&lt;br&gt;f2(1, 2)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 2&lt;/span&gt;&lt;/div&gt; &lt;p&gt;Another parameter attribute (&lt;a href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.optionalattribute.aspx"&gt;OptionalAttribute&lt;/a&gt;) received similar treatment from IronPython: you do not need pass in values either; IronPython assign it a special value (the .NET run-time default value for most of primitive types, &lt;a href="https://msdn2.microsoft.com/en-us/library/system.type.missing.aspx"&gt;System.Type.Missing.&lt;/a&gt;Value for "object" type, null otherwise). Such supports are useful when using IronPython to call into the COM libraries (such as Office automation). The user can avoid typing in every arguments.&lt;/p&gt; &lt;div class="csharp"&gt;&amp;nbsp;&lt;span class="cskeyword"&gt;public void&lt;/span&gt; M6([&lt;span class="cstype"&gt;Optional&lt;/span&gt;] &lt;span class="cskeyword"&gt;int &lt;/span&gt;x, [&lt;span class="cstype"&gt;Optional&lt;/span&gt;] &lt;span class="cskeyword"&gt;object &lt;/span&gt;y) { &lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(&lt;span class="csstring"&gt;"{0} {1}"&lt;/span&gt;, x, y); &lt;br&gt;}&lt;br&gt;&amp;nbsp;&lt;span class="cskeyword"&gt;public void&lt;/span&gt; M7([&lt;span class="cstype"&gt;Optional&lt;/span&gt;] &lt;span class="cskeyword"&gt;string &lt;/span&gt;x, [&lt;span class="cstype"&gt;Optional&lt;/span&gt;] &lt;span class="cstype"&gt;Type &lt;/span&gt;y) { &lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;span class="cstype"&gt;Console&lt;/span&gt;.WriteLine(&lt;span class="csstring"&gt;"{0} {1}"&lt;/span&gt;, x == &lt;span class="cskeyword"&gt;null&lt;/span&gt;, y == &lt;span class="cskeyword"&gt;null&lt;/span&gt;); &lt;br&gt;}&lt;/div&gt; &lt;div class="csharp"&gt;o.M6()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;# print: 0 System.Type.Missing&lt;/span&gt;&lt;br&gt;o.M6(10)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10 System.Type.Missing&lt;/span&gt;&lt;br&gt;o.M6(20, "hi")&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 20 hi&lt;/span&gt;&lt;br&gt;o.M7()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="cscomment"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; True True&lt;/span&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5230964" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>IronPython: Grab the .NET Type</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/09/25/5130087.aspx</link><pubDate>Wed, 26 Sep 2007 00:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5130087</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5130087</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/09/25/5130087.aspx#comments</comments><description>&lt;P&gt;After loading the assembly by &lt;A class="" href="http://blogs.msdn.com/haibo_luo/archive/2007/09/25/5130072.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2007/09/25/5130072.aspx"&gt;clr.AddReference&lt;/A&gt; and then import namespace, we are ready to take hold of types and down-level namespaces using "&lt;A href="http://docs.python.org/ref/attribute-references.html" mce_href="http://docs.python.org/ref/attribute-references.html"&gt;attribute references&lt;/A&gt;". &lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import System&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.DateTime&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # type&lt;BR&gt;&amp;lt;type 'DateTime'&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Diagnostics&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # still namespace&lt;BR&gt;&amp;lt;module 'Diagnostics' (CLS module, 2 assemblies loaded)&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Diagnostics.Debug&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # type again&lt;BR&gt;&amp;lt;type 'Debug'&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Diagnostics.CodeAnalysis&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # namespace again&lt;BR&gt;&amp;lt;module 'CodeAnalysis' (CLS module from mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/DIV&gt;
&lt;P&gt;We can also access public nested type from the declaring type same way. (I was unable to find such example in mscorlib.dll/system.dll)&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cscomment&gt;// lib.cs &lt;/SPAN&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;&amp;nbsp;&amp;nbsp; &lt;SPAN class=cskeyword&gt;public class&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;NestedC &lt;/SPAN&gt;{} &lt;BR&gt;}&lt;/DIV&gt;
&lt;DIV class=csharp&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import clr&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;clr.AddReference("lib")&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import C &lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # C has no namespace here&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;C.NestedC&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;type 'NestedC'&amp;gt;&lt;/DIV&gt;
&lt;P&gt;When the type is generic type, such attribute reference returns the &lt;A href="http://msdn2.microsoft.com/en-us/library/ms172334.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms172334.aspx"&gt;open generic type&lt;/A&gt;. We need then call the index operation (&lt;A href="http://docs.python.org/ref/subscriptions.html" mce_href="http://docs.python.org/ref/subscriptions.html"&gt;subscriptions&lt;/A&gt;) to construct the closed generic type, and do something interesting with it. A type tuple is expected as the index, but the parentheses can be omitted most of time. &lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Collections.Generic.Dictionary&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # open generic type&lt;BR&gt;&amp;lt;type 'Dictionary[TKey, TValue]'&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Collections.Generic.Dictionary[int, str]&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # closed generic type&lt;BR&gt;&amp;lt;type 'Dictionary[int, str]'&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Collections.Generic.Dictionary[(int, object)]&lt;/SPAN&gt;&amp;nbsp; # closed generic type&lt;BR&gt;&amp;lt;type 'Dictionary[int, object]'&amp;gt;&lt;/DIV&gt;
&lt;P&gt;Also the .NET type names could be "same" or similar; one example is System.Nullable and System.Nullable&amp;lt;T&amp;gt; in mscorlib.dll. Many experimental code of mine has types like C, C&amp;lt;T&amp;gt;, C&amp;lt;T1, T2&amp;gt; . As shown below, "System.Nullable" now returns a type group, including 2 types. In order to distinguish the non-generic type from the generic one, an empty tuple need be passed in as index.&lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Nullable&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;types 'Nullable', 'Nullable[T]'&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Nullable[()]&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # get the non-generic type&lt;BR&gt;&amp;lt;type 'Nullable'&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Nullable[System.DateTime]&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;type 'Nullable[DateTime]'&amp;gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5130087" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>IronPython: clr.AddReference</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/09/25/5130072.aspx</link><pubDate>Wed, 26 Sep 2007 00:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5130072</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5130072</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/09/25/5130072.aspx#comments</comments><description>&lt;P&gt;In order to interop with .NET libraries, we need first load in the assemblies we want to play with. The family of AddReference methods in the &lt;EM&gt;clr&lt;/EM&gt; module serves the purpose.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;clr.AddReference 
&lt;LI&gt;clr.AddReferenceByName 
&lt;LI&gt;clr.AddReferenceByPartialName 
&lt;LI&gt;clr.AddReferenceToFile 
&lt;LI&gt;clr.AddReferenceToFileAndPath &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;clr.AddReference&lt;/STRONG&gt; accepts System.Reflection.Assembly objects and/or assembly names. The typical usage looks like:&lt;/P&gt;
&lt;DIV class=csharp&gt;asm = ... # any approach of getting an Assembly object&lt;BR&gt;clr.AddReference(asm)&lt;BR&gt;clr.AddReference("System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")&lt;BR&gt;clr.AddReference("System.Drawing")&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;If a string is passed in, Assembly.Load(string) is used to load the assembly. If failed, it re-tries with Assembly.LoadWithPartialName(string).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;clr.AddReferenceByName&lt;/STRONG&gt; basically is the wrapper of &lt;A href="https://msdn2.microsoft.com/en-us/library/ky3942xh.aspx" mce_href="https://msdn2.microsoft.com/en-us/library/ky3942xh.aspx"&gt;Assembly.Load&lt;/A&gt;, which means the assembly full name is expected. Similarly, &lt;STRONG&gt;clr.AddReferenceByPartialName&lt;/STRONG&gt; is the wrapper around the obsolete &lt;A href="https://msdn2.microsoft.com/en-us/library/12xc5368.aspx" mce_href="https://msdn2.microsoft.com/en-us/library/12xc5368.aspx"&gt;Assembly.LoadWithPartialName&lt;/A&gt;: "System.Drawing" and "System.Drawing, Version=2.0.0.0" are examples of valid arguments. &lt;/P&gt;
&lt;P&gt;A typical usage of &lt;STRONG&gt;clr.AddReferenceToFile &lt;/STRONG&gt;looks like: &lt;/P&gt;
&lt;DIV class=csharp&gt;clr.AddReferenceToFile("my1.dll", "my2")&amp;nbsp; # load my1.dll and my2.dll&lt;/DIV&gt;
&lt;P&gt;It expects file name(s) without the directory path as the argument. To locate my1.dll, it searches each directory in sys.path until the specified file is found (it also tries to append ".dll" or ".exe"). Behind the scene, the loading is via &lt;A href="https://msdn2.microsoft.com/en-us/library/b61s44e8.aspx" mce_href="https://msdn2.microsoft.com/en-us/library/b61s44e8.aspx"&gt;Assembly.LoadFile&lt;/A&gt;. Normally sys.path includes the current working directory; so if my1.dll and my2.dll exist in the current directory, clr.AddReferenceToFile("my1.dll", "my2") should succeed. If you know the exact full path of a clr assembly, you may use &lt;STRONG&gt;clr.AddReferenceToFileAndPath&lt;/STRONG&gt; to load. As a by-product, the path of the assembly file will be appended to sys.path. Note &lt;A href="https://msdn2.microsoft.com/en-us/library/system.reflection.assembly.loadfrom.aspx" mce_href="https://msdn2.microsoft.com/en-us/library/system.reflection.assembly.loadfrom.aspx"&gt;Assembly.LoadFrom&lt;/A&gt; is never used underneath by these 5 methods due to the &lt;A href="http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx" mce_href="http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx"&gt;loading context&lt;/A&gt; concern.&lt;/P&gt;
&lt;P&gt;We can use &lt;STRONG&gt;clr.References&lt;/STRONG&gt; to list which assemblies have been loaded. The output shows that mscorlib.dll and System.dll are implicitly loaded/added (without the need of calling clr.AddReference).&lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import clr&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;for r in clr.References: print r&lt;/SPAN&gt;&lt;BR&gt;...&lt;BR&gt;mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;BR&gt;System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;clr.AddReference("System.Drawing")&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;for r in clr.References: print r &lt;/SPAN&gt;&lt;BR&gt;...&lt;BR&gt;mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 &lt;BR&gt;System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 &lt;BR&gt;System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&lt;/DIV&gt;
&lt;P&gt;By treating the namespace like the python module, IronPython extends the &lt;EM&gt;import&lt;/EM&gt; statement semantics to bring in the clr namespace. In current implementation the "classical" python module is still preferred by &lt;EM&gt;import&lt;/EM&gt;: given the statement "import MyLib", if the file "MyLib.py" is present under any directory of sys.path, that file will be imported; if not, for each loaded assembly, import tries to find the namespace "MyLib". Although not common in well-designed .NET frameworks, a type could have empty namespace; so "import MyLib" also tries to find type "MyLib" in the loaded assemblies.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The namespace of "MyLib" could exist more than 1 loaded assemblies. The following snippet shows that, "import System" adds a CLS module to sys.modules and this CLS module contains members from 2 assemblies: mscorlib.dll and System.dll (since both assemblies has types and down-level namespaces like System.*).&amp;nbsp; &lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;gt; &lt;SPAN class=typein&gt;ipy.exe&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import sys&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;sys.modules.keys()&lt;/SPAN&gt;&lt;BR&gt;['sys', '__builtin__', '__main__', 'site']&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import System&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;sys.modules.keys()&lt;/SPAN&gt;&lt;BR&gt;['sys', '__builtin__', '__main__', 'site', 'System']&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;sys.modules['System']&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;module 'System' (CLS module, 2 assemblies loaded)&amp;gt; &lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System == sys.modules['System']&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #&amp;nbsp;better use "is" to check identity as Michael pointed out in the comment&lt;BR&gt;True&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.__file__&lt;/SPAN&gt;&lt;BR&gt;['mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089', 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089']&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;System.Console.WriteLine('later')&lt;/SPAN&gt;&lt;BR&gt;later&lt;BR&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5130072" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>IronPython: import clr</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2007/09/25/5130066.aspx</link><pubDate>Wed, 26 Sep 2007 00:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5130066</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=5130066</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/09/25/5130066.aspx#comments</comments><description>&lt;P&gt;&lt;EM&gt;clr&lt;/EM&gt; is an IronPython built-in module, which provides some functionalities in order to interop with .NET. When writing "import clr" in a python module, it means you intend to leverage the .NET libraries. One classical example is python string's methods. In IronPython, python type &lt;I&gt;str&lt;/I&gt; is implemented by the .NET type &lt;I&gt;System.String&lt;/I&gt;. We can call System.String's methods on string objects after the line of "import clr" (see the example below); of course those python string methods are still available.&lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;gt; &lt;SPAN class=typein&gt;ipy.exe&lt;/SPAN&gt;&lt;BR&gt;IronPython console: IronPython 2.0 (2.0.0.00) on .NET 2.0.50727.1378&lt;BR&gt;Copyright (c) Microsoft Corporation. All rights reserved. &lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;s = "IronPython"&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;s.upper()&lt;/SPAN&gt;&lt;BR&gt;'IRONPYTHON'&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;s.ToUpper()&lt;/SPAN&gt;&lt;BR&gt;Traceback (most recent call last):&lt;BR&gt;&amp;nbsp; File , line 0, in ##14&lt;BR&gt;&amp;nbsp; File , line 0, in _stub_##15&lt;BR&gt;AttributeError: 'str' object has no attribute 'ToUpper'&lt;BR&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import clr&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;s.upper()&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # python method still works&lt;BR&gt;'IRONPYTHON'&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;s.ToUpper()&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # works&lt;BR&gt;'IRONPYTHON'&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Such context change is per-python-module. Although lib.py (below) imports the &lt;EM&gt;clr&lt;/EM&gt; module and app.py then imports the &lt;I&gt;lib&lt;/I&gt; module, app.py will not see the .NET methods. Running this app.py under C-Python will fail (ImportError) due to the usage of the clr module in lib.py. But if we make lib.py platform-neutral next time, we are ensured that no change in app.py is needed in order to run it under both C-Python and IronPython.&lt;/P&gt;
&lt;DIV class=csharp&gt;# lib.py&lt;BR&gt;import clr&lt;BR&gt;def my_upper(s): return s.ToUpper() &lt;/DIV&gt;
&lt;DIV class=csharp&gt;# app.py&lt;BR&gt;import lib&lt;BR&gt;s = "hello world"&lt;BR&gt;print lib.my_upper(s)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # print "HELLO WORLD"&lt;BR&gt;#print s.ToUpper()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # AttributeError would throw&lt;BR&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5130066" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>DebuggerTypeProxy for IronPython Old-style Class and Instance</title><link>http://blogs.msdn.com/b/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 - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=4210344</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2007/08/03/4210344.aspx#comments</comments><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/cfs-file.ashx/__key/communityserver-components-postattachments/00-04-21-03-44/proxytype.zip" length="8704" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/Reflection-Emit/">Reflection.Emit</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>Name of Array Type</title><link>http://blogs.msdn.com/b/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 - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=1169887</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/11/28/1169887.aspx#comments</comments><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;div style="clear:both;"&gt;&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/b/haibo_luo/archive/tags/Reflection/">Reflection</category></item><item><title>Late-bound Array SetValue</title><link>http://blogs.msdn.com/b/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 - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=1157785</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/11/26/1157785.aspx#comments</comments><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;div style="clear:both;"&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/cfs-file.ashx/__key/communityserver-components-postattachments/00-01-15-77-85/ArraySetValue_2E00_cs" length="3690" type="text/plain" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/Reflection/">Reflection</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/DynamicMethod/">DynamicMethod</category></item><item><title>Take Two: IL Visualizer</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx</link><pubDate>Fri, 17 Nov 2006 00:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1090671</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=1090671</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx#comments</comments><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;P&gt;update (4/19/2010): VS2010 solution can be found at &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2010/04/19/9998595.aspx"&gt;http://blogs.msdn.com/haibo_luo/archive/2010/04/19/9998595.aspx&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1090671" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-01-09-06-71/ILVisualizer.zip" length="48737" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/Reflection/">Reflection</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/DynamicMethod/">DynamicMethod</category></item><item><title>Turn MethodInfo to DynamicMethod</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2006/11/07/turn-methodinfo-to-dynamicmethod.aspx</link><pubDate>Wed, 08 Nov 2006 01:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1023508</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=1023508</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/11/07/turn-methodinfo-to-dynamicmethod.aspx#comments</comments><description>&lt;P&gt;I do not know why anyone ever need this :) but few readers did ask me similar questions before. Solving this problem also demonstrates one more &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2006/11/06/system-reflection-based-ilreader.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/11/06/system-reflection-based-ilreader.aspx"&gt;ILReader&lt;/A&gt; usage.&lt;/P&gt;
&lt;P&gt;To build a DynamicMethod, we can choose either &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.ilgenerator.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.ilgenerator.aspx"&gt;DynamicILGenerator&lt;/A&gt; or &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.aspx"&gt;DynamicILInfo&lt;/A&gt;. My first impression of using DynamicILGenerator to emit code is slow: you need make calls to emit ILs instruction by instruction. Actually this approach is more difficult, a topic for future post. I already wrote a &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx"&gt;post&lt;/A&gt; about DynamicILInfo. I do not know the motivation behind the DynamicILInfo class (at that time I was not in the CLR team), but I heard this was a feature request from SQL.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To turn a MethodInfo to DynamicMethod, we can not simply call &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.setcode.aspx"&gt;SetCode&lt;/A&gt; with the byte array returned by the static method body's &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.getilasbytearray.aspx"&gt;GetILAsByteArray&lt;/A&gt;. Those tokens (if any) are metadata tokens, meaningful only in the scope of the module where that static method lives. The &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.gettokenfor.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicilinfo.gettokenfor.aspx"&gt;DynamicILInfo.GetTokenFor&lt;/A&gt; overloads are designed to build the relationship between an integer number (the new "token") and the runtime member (type, method, field, string, or signature...) in the scope of the dynamic method.&amp;nbsp;We can first make a copy of the static method's IL byte array, and overwrite the old metadata token with the new token from GetTokenFor for each applicable IL instruction. So here comes ILInfoGetTokenVisitor. As you see, we override 6 visit methods in ILInfoGetTokenVisitor, doing the token replacements; the top-level code to prepare new code array looks simple.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;class&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILInfoGetTokenVisitor&lt;/SPAN&gt; : &lt;SPAN class=cstype&gt;ILInstructionVisitor&lt;/SPAN&gt; {&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; private&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;DynamicILInfo&lt;/SPAN&gt; ilInfo;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; private byte&lt;/SPAN&gt;[] code;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILInfoGetTokenVisitor&lt;/SPAN&gt;(&lt;SPAN class=cstype&gt;DynamicILInfo&lt;/SPAN&gt; ilinfo, &lt;SPAN class=cskeyword&gt;byte&lt;/SPAN&gt;[] code) {&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; &amp;nbsp; this&lt;/SPAN&gt;.ilInfo = ilinfo;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; &amp;nbsp; this&lt;/SPAN&gt;.code = code;&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineMethodInstruction(&lt;SPAN class=cstype&gt;InlineMethodInstruction&lt;/SPAN&gt; inlineMethodInstruction) {&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ilInfo.GetTokenFor(inlineMethodInstruction.Method.MethodHandle,&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; inlineMethodInstruction.Method.DeclaringType.TypeHandle),&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; inlineMethodInstruction.Offset + inlineMethodInstruction.OpCode.Size);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineFieldInstruction(&lt;SPAN class=cstype&gt;InlineFieldInstruction&lt;/SPAN&gt; inlineFieldInstruction) { ... }&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineSigInstruction(&lt;SPAN class=cstype&gt;InlineSigInstruction&lt;/SPAN&gt; inlineSigInstruction) { ... } &lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineStringInstruction(&lt;SPAN class=cstype&gt;InlineStringInstruction&lt;/SPAN&gt; inlineStringInstruction) { ... }&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineTokInstruction(&lt;SPAN class=cstype&gt;InlineTokInstruction&lt;/SPAN&gt; inlineTokInstruction) { ... }&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; public override void&lt;/SPAN&gt; VisitInlineTypeInstruction(&lt;SPAN class=cstype&gt;InlineTypeInstruction&lt;/SPAN&gt; inlineTypeInstruction) { ... }&lt;BR&gt;&amp;nbsp; ...&lt;BR&gt;} &lt;BR&gt;&lt;/DIV&gt;&lt;BR&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;private static void&lt;/SPAN&gt; SetCode(&lt;SPAN class=cstype&gt;MethodInfo&lt;/SPAN&gt; method, &lt;SPAN class=cstype&gt;MethodBody&lt;/SPAN&gt; body, &lt;SPAN class=cstype&gt;DynamicILInfo&lt;/SPAN&gt; ilInfo) {&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; byte&lt;/SPAN&gt;[] code = body.GetILAsByteArray(); &lt;BR&gt;&lt;SPAN class=cstype&gt;&amp;nbsp; ILReader&lt;/SPAN&gt; reader = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILReader&lt;/SPAN&gt;(method);&lt;BR&gt;&lt;SPAN class=cstype&gt;&amp;nbsp; ILInfoGetTokenVisitor&lt;/SPAN&gt; visitor = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cstype&gt;ILInfoGetTokenVisitor&lt;/SPAN&gt;(ilInfo, code);&lt;BR&gt;&amp;nbsp; reader.Accept(visitor); &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ilInfo.SetCode(code, body.MaxStackSize);&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;JAY was asking &lt;A href="http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx#527435" mce_href="http://blogs.msdn.com/haibo_luo/archive/2006/01/30/519984.aspx#527435"&gt;how to set exceptions&lt;/A&gt;. Reflection does not provide API to return the exception blob directly, instead the exception information is exposed through the &lt;A href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.exceptionhandlingclauses.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.methodbody.exceptionhandlingclauses.aspx"&gt;MethodBody.ExceptionHandlingClauses&lt;/A&gt; property. With this ExceptionHandlingClause list, we can follow the format described by Ecma 335 (Part 2, 25.4.5 and 25.4.6) and build the exception blob from scratch. To avoid worrying about the restriction of the small version of exception handling clauses, the exception array generated below is with the fat form layout. See some comments inside the code.&lt;/P&gt;
&lt;DIV class=csharp&gt;&lt;SPAN class=cskeyword&gt;private static void&lt;/SPAN&gt; SetExceptions(&lt;SPAN class=cstype&gt;MethodBody&lt;/SPAN&gt; body, &lt;SPAN class=cstype&gt;DynamicILInfo&lt;/SPAN&gt; ilInfo) {&lt;BR&gt;&lt;SPAN class=cstype&gt;&amp;nbsp; IList&lt;/SPAN&gt;&amp;lt;&lt;SPAN class=cstype&gt;ExceptionHandlingClause&lt;/SPAN&gt;&amp;gt; ehcs = body.ExceptionHandlingClauses;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; int&lt;/SPAN&gt; ehCount = ehcs.Count;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; if&lt;/SPAN&gt; (ehCount == 0) &lt;SPAN class=cskeyword&gt;return&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cscomment&gt;&amp;nbsp; // Let us do FAT exception header&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; int&lt;/SPAN&gt; size = 4 + 24 * ehCount;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; byte&lt;/SPAN&gt;[] exceptions = &lt;SPAN class=cskeyword&gt;new&lt;/SPAN&gt; &lt;SPAN class=cskeyword&gt;byte&lt;/SPAN&gt;[size];&lt;BR&gt;&lt;BR&gt;&amp;nbsp; exceptions[0] = 0x01 | 0x40; &lt;SPAN class=cscomment&gt;//Offset: 0, Kind: CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp; OverwriteInt32(size, 1, exceptions); &lt;SPAN class=cscomment&gt;// Offset: 1, DataSize: n * 24 + 4&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; int&lt;/SPAN&gt; pos = 4;&lt;BR&gt;&lt;SPAN class=cskeyword&gt;&amp;nbsp; foreach&lt;/SPAN&gt; (&lt;SPAN class=cstype&gt;ExceptionHandlingClause&lt;/SPAN&gt; ehc &lt;SPAN class=cskeyword&gt;in&lt;/SPAN&gt; ehcs) {&lt;BR&gt;&lt;SPAN class=cscomment&gt;&amp;nbsp; &amp;nbsp; // Flags, TryOffset, TryLength, HandlerOffset, HandlerLength: all size 4&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32((&lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt;)ehc.Flags, pos, exceptions); pos += 4;&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.TryOffset, pos, exceptions); pos += 4;&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.TryLength, pos, exceptions); pos += 4;&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.HandlerOffset, pos, exceptions); pos += 4;&lt;BR&gt;&amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.HandlerLength, pos, exceptions); pos += 4; &lt;BR&gt;&lt;BR&gt;&lt;SPAN class=cscomment&gt;&amp;nbsp; &amp;nbsp; // ClassToken or FilterOffset&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;switch&lt;/SPAN&gt; (ehc.Flags) {&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;case&lt;/SPAN&gt; ExceptionHandlingClauseOptions.Clause:&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;int&lt;/SPAN&gt; token = ilInfo.GetTokenFor(ehc.CatchType.TypeHandle);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; OverwriteInt32(token, pos, exceptions);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;case&lt;/SPAN&gt; ExceptionHandlingClauseOptions.Filter:&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; OverwriteInt32(ehc.FilterOffset, pos, exceptions);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;case&lt;/SPAN&gt; ExceptionHandlingClauseOptions.Fault:&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;throw new&lt;/SPAN&gt; NotSupportedException(&lt;SPAN class=csstring&gt;"dynamic method does not support fault clause"&lt;/SPAN&gt;);&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;case&lt;/SPAN&gt; ExceptionHandlingClauseOptions.Finally:&lt;BR&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN class=cskeyword&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp; &amp;nbsp; }&lt;BR&gt;&amp;nbsp; &amp;nbsp; pos += 4;&lt;BR&gt;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ilInfo.SetExceptions(exceptions);&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;If you are interested in the details, you may download the attachment and read the whole source code closely.&lt;/P&gt;
&lt;P&gt;A related question is how to build a dynamic method from other sources. DynamicMethod is not &lt;A href="http://msdn2.microsoft.com/en-us/library/system.serializableattribute.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.serializableattribute.aspx"&gt;Serializable&lt;/A&gt;, .NET framework built-in serializing/deserializing support will not work. One approach I can think of is to preserve the code array, the members/strings/... (in order to call GetTokenFor to get new tokens) used and their matching offsets (with one scan of&amp;nbsp;the ILs). MethodInfo, FieldInfo, Type are marked "Serializable", but not sure whether this is the right way to save/restore those members. If the method handles exception, we can save the pre-calculated exception blob, and remember where we need replace token for what exception type.&lt;/P&gt;
&lt;P&gt;Finally, let us play with the turn-static-method-to-dynamic-method call, and show off some IronPython code. The first 3 lines bring in the DynamicMethodHelper class. Then we use Reflection to get DateTime.get_Now's MethodInfo (sGetNow), and convert it to DynamicMethod (dGetNow) with "DynamicMethodHelper.ConvertFrom". The last part of the code is interesting: it converts the method "DynamicMethodHelper.ConvertFrom" to DynamicMethod (dConvert), and use that dynamic method (dConvert) to convert sGetNow to another dynamic method (dGetNow2). Just fyi: DateTime.get_Now has 5 instructions, DynamicMethodHelper.ConvertFrom has ~80 instructions and exception handlings clauses.&lt;/P&gt;
&lt;DIV class=csharp&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;import clr, System&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;clr.AddReference('ClrTest.Reflection.DynamicMethodHelper.dll')&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;from ClrTest.Reflection import *&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;clr.GetClrType(System.DateTime).GetMethod("get_Now")&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.RuntimeMethodInfo object at 0x000000000000002B [System.DateTime get_Now()]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;sGetNow = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;DynamicMethodHelper.ConvertFrom(sGetNow)&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.Emit.DynamicMethod object at 0x000000000000002C [System.DateTime get_Now()]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dGetNow = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dGetNow.Invoke(None, None)&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.DateTime object at 0x000000000000002D [11/7/2006 11:40:49 AM]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;clr.GetClrType(DynamicMethodHelper).GetMethod("ConvertFrom")&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.RuntimeMethodInfo object at 0x000000000000002E [System.Reflection.Emit.DynamicMethod ConvertFrom(System.Reflection.MethodInfo)]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;sConvert = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;DynamicMethodHelper.ConvertFrom(sConvert)&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.Emit.DynamicMethod object at 0x000000000000002F [System.Reflection.Emit.DynamicMethod ConvertFrom(System.Reflection.MethodInfo)]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dConvert = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dConvert.Invoke(None, System.Array[object]([sGetNow]))&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.Reflection.Emit.DynamicMethod object at 0x0000000000000030 [System.DateTime get_Now()]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dGetNow2 = _&lt;/SPAN&gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; &lt;SPAN class=typein&gt;dGetNow2.Invoke(None, None)&lt;/SPAN&gt;&lt;BR&gt;&amp;lt;System.DateTime object at 0x0000000000000031 [11/7/2006 11:40:59 AM]&amp;gt;&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;BR&gt;&lt;/DIV&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1023508" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-01-02-35-08/DynamicMethodHelper_2E00_cs" length="8862" type="text/plain" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/DynamicMethod/">DynamicMethod</category></item><item><title>System.Reflection-based ILReader</title><link>http://blogs.msdn.com/b/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 - MSFT</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=1003788</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/11/06/system-reflection-based-ilreader.aspx#comments</comments><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/cfs-file.ashx/__key/communityserver-components-postattachments/00-01-00-37-88/ILReader.zip" length="8744" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/Reflection/">Reflection</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/DynamicMethod/">DynamicMethod</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/IronPython/">IronPython</category></item><item><title>Always Peverify IL Code of your Dynamic Method</title><link>http://blogs.msdn.com/b/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 - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=1038287</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/10/31/always-peverify-il-code-of-your-dynamic-method.aspx#comments</comments><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/b/haibo_luo/archive/tags/Reflection-Emit/">Reflection.Emit</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/DynamicMethod/">DynamicMethod</category></item><item><title>Shift Away from CLR Reflection Area</title><link>http://blogs.msdn.com/b/haibo_luo/archive/2006/10/31/shift-away-from-clr-reflection-area.aspx</link><pubDate>Wed, 01 Nov 2006 07:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1038298</guid><dc:creator>Haibo Luo - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=1038298</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/10/31/shift-away-from-clr-reflection-area.aspx#comments</comments><description>&lt;P&gt;After 2-year&amp;nbsp;Reflection test ownership&amp;nbsp;and&amp;nbsp;1-year&amp;nbsp;babysitting for Reflection.Emit and DynamicMethod areas, I am gradually away from these CLR feature areas, and&amp;nbsp;will be more focusing on &lt;A href="http://www.codeplex.com/ironpython" mce_href="http://www.codeplex.com/ironpython"&gt;IronPython&lt;/A&gt; (and maybe others later). 
&lt;P&gt;Before completely&amp;nbsp;leaving them behind, first of all,&amp;nbsp;I want to apologize to you if you sent me emails about this blog before and I did not reply. I plan to answer some of those emails in the coming posts. 
&lt;P&gt;Also I will try my best to share more of what I learned&amp;nbsp;last 2 years, before I forget them. If you have anything&amp;nbsp;particular you want to discuss, please leave a comment. 
&lt;P&gt;Thanks for listening.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1038298" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/Miscellaneous/">Miscellaneous</category></item><item><title>ILGenerator.EmitCall Mainly For vararg Methods</title><link>http://blogs.msdn.com/b/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 - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=698719</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/08/13/698719.aspx#comments</comments><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/cfs-file.ashx/__key/communityserver-components-postattachments/00-00-69-87-19/VarargMethod_2E00_cs" length="2807" type="text/plain" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/Reflection-Emit/">Reflection.Emit</category><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/DynamicMethod/">DynamicMethod</category></item><item><title>Member Order Returned by GetFields, GetMethods ...</title><link>http://blogs.msdn.com/b/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 - MSFT</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/haibo_luo/rsscomments.aspx?WeblogPostID=661091</wfw:commentRss><comments>http://blogs.msdn.com/b/haibo_luo/archive/2006/07/09/661091.aspx#comments</comments><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;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=661091" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-00-66-10-91/MemberOrder_2E00_cs" length="566" type="text/plain" /><category domain="http://blogs.msdn.com/b/haibo_luo/archive/tags/Reflection/">Reflection</category></item></channel></rss>
