<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Managed CodeGen</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/yirutang/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/yirutang/feed.xml</link>
    <description>This blog is to introduce some new features about Managed CodeGen in Whidbey. We provided a new way of doing LightWeight CodeGen, added support for emitting Generics in Reflection.Emit and there is some new exciting token handle stories in Reflection goin</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:27:19 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>A Tool (attached) to help figure out how to emit a type</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/a-tool-attached-to-help-figure-out-how-to-emit-a-type</link>
      <pubDate>Wed, 07 Jun 2006 16:07:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2006/06/07/a-tool-attached-to-help-figure-out-how-to-emit-a-type/</guid>
      <description><![CDATA[After being in Exchange for almost a year, I&nbsp;tend to&nbsp;forget the how to run Reflection.Emit...]]></description>
      <content:encoded><![CDATA[<P>After being in Exchange for almost a year, I&nbsp;tend to&nbsp;forget the how to run Reflection.Emit that I was once so familiared with.&nbsp; Occasionally, I&nbsp;would receive emails from this blog asking how to emit this, how to emit that. Before,&nbsp;the solutions came directly&nbsp;from my memory, but now I need some help. The way for me to figure it out is to compile the thing I want to emit into a binary file and run it under my little tool AssemblyRoundTrip.exe with verbose output. </P>
<P>I wrote the tool for testing purpose. I ran every assembly I can get under that tool and it will figure out for me whether we can or cannot emit the assembly. </P>
<P>Now, I found it really helpful for myself to figure out&nbsp;things should be done. I am posting the tool here and hopefully it will help you to work out some generic mystery.</P>
<P>Here is an example, if I want to define Test&lt;T&gt;:List&lt;T&gt; type, I wrote it in C# and compile it. Then I ran</P>
<P><STRONG>AssemblyRoundTrip.exe repro.dll /verbose</STRONG> </P>
<P>and here is the output:</P>
<P>new Asm Name is repro_Emit<BR>Security Attribute number :0<BR>setting ca:[System.Runtime.CompilerServices.CompilationRelaxationsAttribute((Int<BR>32)8)]<BR>setting ca:[System.Runtime.CompilerServices.RuntimeCompatibilityAttribute(WrapNo<BR>nExceptionThrows = True)]<BR>new module name is repro_Emit.dll<BR>Total Types:1<BR><STRONG>m_modBuilder.DefineType M`1</STRONG>&nbsp;&nbsp;&nbsp;&nbsp; &lt;---- Define the type<BR>Adding M`1[T] to the create list<BR><STRONG>Define Generic Parameters on M`1</STRONG>&nbsp; &lt;---- Define the type parameter<BR>Adding Generic Parameter M`1[T]::T on Type M`1 to the create type list<BR><STRONG>Found a match for :M`1::T</STRONG>&nbsp;&nbsp; &lt;--- this step is a preparation for the type below. We are binding List`1[T] (the type below)&nbsp;to T<BR><STRONG>Set Parent for M`1 System.Collections.Generic.List`1[T]</STRONG>&nbsp; &lt;--- set the paraent<BR>Found a match for :M`1::T<BR>Set Interface for M`1 System.Collections.Generic.IList`1[T]<BR>Found a match for :M`1::T<BR>Set Interface for M`1 System.Collections.Generic.ICollection`1[T]<BR>Found a match for :M`1::T<BR>Set Interface for M`1 System.Collections.Generic.IEnumerable`1[T]<BR>Set Interface for M`1 System.Collections.IEnumerable<BR>Set Interface for M`1 System.Collections.IList<BR>Set Interface for M`1 System.Collections.ICollection<BR>+++ Create Method : M`1[T]::.ctor<BR>Security Attribute for type :M`1[T] is 0<BR>Adding M`1[T] to bake type list<BR>+++ Created Type : M`1</P>
<P>&nbsp;</P>
<P>So I translate the verbose output into the following code:</P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">using System;</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial"></SPAN></FONT><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">using System.Reflection;</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">using System.Collections.Generic;</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">using System.Reflection.Emit;</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial"></SPAN></FONT>&nbsp;</P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">public class Test</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">{</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void Main()</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string typename = "ListProxy";</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AssemblyName asmname = new AssemblyName("mytest");</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; AssemblyBuilder asmbuild = AppDomain.CurrentDomain.DefineDynamicAssembly(asmname, AssemblyBuilderAccess.RunAndSave);</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ModuleBuilder moduleBuilder = asmbuild.DefineDynamicModule("mytest", "mytest.dll");</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.Class;</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TypeBuilder typeBuilder = moduleBuilder.DefineType(typename, typeAttributes); </SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GenericTypeParameterBuilder[] tpbs = typeBuilder.DefineGenericParameters("T"); // defines a generic type definition</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; typeBuilder.MakeGenericType(typeof(List&lt;&gt;).GetGenericArguments()[0]);&nbsp;&nbsp; </SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; typeBuilder.SetParent(typeof(List&lt;&gt;).MakeGenericType(tpbs[0])); // bind the correct base type</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; typeBuilder.CreateType(); </SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; asmbuild.Save("mytest");</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</SPAN></FONT></P>
<P class=MsoNormal><FONT face=Arial color=navy size=2><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial">}</SPAN></FONT></P>
<P>I attached the tool as it is and I am <STRONG>unlikely</STRONG> to support this tool. I could send the source code upon request but the source code is a little confusing since it is a test tool so it tend to has many extra stuff that we are interested to test but not related to the main purpose.</P>
<P>If you set EXT_ROOT to your runtime install path, the tool will run peverify for you at the end to verify the generated assembly.</P>
<P>You will find there is another AssemblyPrinter.exe, it is a reflection verstion of ildasm outputing text file. The only difference is that AssemblyPrinter.exe prints out members in deterministic order. So if you want to compare the two assemblies, AssemblyPrinter.exe is a good tool for that. ildasm.exe output on two assemblies compiled from the same source tend to be difference because the runtime doesn't grarantee the ordering of members to be the same. (This should remind you not to use GetMethods[1] or GetCustomAttributes[2] since they tend to change!)</P>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/00/62/11/25/ILReader.rar" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-00-62-11-25/ILReader.rar">ILReader.rar</a></p>]]></content:encoded>
    </item>
    <item>
      <title>I am moving onto Exchange Team</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/i-am-moving-onto-exchange-team</link>
      <pubDate>Fri, 09 Dec 2005 15:22:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/12/09/i-am-moving-onto-exchange-team/</guid>
      <description><![CDATA[I am&nbsp;going&nbsp;to program in the&nbsp;Server world&nbsp;using managed code! Maybe after some...]]></description>
      <content:encoded><![CDATA[<P>I am&nbsp;going&nbsp;to program in the&nbsp;Server world&nbsp;using managed code! Maybe after some time, I will start a new blog for IT professionals about Clustering in Exchange. But currently this blog is not likely to have new contents about the most updated CLR technology.</P>
<P>Thanks.</P>
<P>Yiru</P>]]></content:encoded>
    </item>
    <item>
      <title>Sample Code to invoke managed code inside profiling API</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/sample-code-to-invoke-managed-code-inside-profiling-api</link>
      <pubDate>Fri, 09 Dec 2005 15:01:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/12/09/sample-code-to-invoke-managed-code-inside-profiling-api/</guid>
      <description><![CDATA[ProfilerCallback.cpp
//&nbsp;This is the function&nbsp;that will invoke the managed code through...]]></description>
      <content:encoded><![CDATA[<P>ProfilerCallback.cpp</P>
<P><BR>//&nbsp;This is the function&nbsp;that will invoke the managed code through COM interop on another thread</P>
<P>// this function creates the CCW object</P>
<P>// [in] this pointer<BR>DWORD WINAPI CreateManagedStub(LPVOID lpParam)<BR>{<BR>&nbsp;&nbsp;&nbsp; _ManagedStub * pIManagedStub = NULL;<BR>&nbsp;&nbsp;&nbsp; HRESULT hr = CoCreateInstance(CLSID_ManagedStub, NULL, CLSCTX_INPROC_SERVER, IID__ManagedStub, (void **)&amp;pIManagedStub);&nbsp;<BR>&nbsp;&nbsp;&nbsp; if (FAILED(hr))<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("Fail to CoCreateInstance on ManagedStub class 0x%x\n", hr);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<BR>&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp; if (pIManagedStub == NULL)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("pIManagedStub is null 0x%x\n", hr);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<BR>&nbsp;&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp;&nbsp; // we have the managed instance now.<BR>&nbsp;&nbsp;&nbsp; ((CProfilerCallback*)lpParam)-&gt;m_pIManagedStub = pIManagedStub;<BR>&nbsp;&nbsp;&nbsp; return 0;<BR>}</P>
<P>//&nbsp;this function is the actual caller to the managed world.&nbsp;<BR>// this function can be used to get a managed dynamic method token back<BR>// [in] this pointer; method token; assembly name<BR>// [out] delegate type name<BR>DWORD WINAPI ManagedPreStub(LPVOID lpParam)<BR>{<BR>&nbsp;&nbsp;&nbsp; PMYDATA pData = (PMYDATA)lpParam;<BR>&nbsp;&nbsp;&nbsp; LPWSTR delegateName = NULL;<BR>&nbsp;&nbsp;&nbsp; if (pData-&gt;thisObj-&gt;m_pIManagedStub == NULL)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("pData-&gt;thisObj-&gt;m_pIManagedStub is null");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; HRESULT hr = pData-&gt;thisObj-&gt;m_pIManagedStub-&gt;PreStub(pData-&gt;assemblyName, pData-&gt;methodTk, &amp;delegateName);<BR>&nbsp;&nbsp;&nbsp; if (FAILED(hr))<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("Fail to Call PreStub 0x%x\n", hr);<BR>&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp; wcscpy_s(pData-&gt;delegateName, (wchar_t*)delegateName);<BR>&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;&nbsp; <BR>}</P>
<P>......</P>
<P>// Profiler callback function</P>
<P>HRESULT CProfilerCallback::JITCompilationStarted(UINT functionId,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BOOL fIsSafeToBlock)<BR>{<BR>&nbsp;&nbsp;&nbsp; HANDLE hThread = NULL;<BR>&nbsp;&nbsp;&nbsp; DWORD dwThreadId;<BR>&nbsp;&nbsp;&nbsp; /////////////////////////////////////////////////////////<BR>&nbsp;&nbsp;&nbsp; //&nbsp;We dont want to continue on JITCompilationStarted if the thread is for the "managed code" we are to call from&nbsp;this callback.</P>
<P>&nbsp;&nbsp;&nbsp; // We store these thread ids in our skip thread hashtable</P>
<P>&nbsp;&nbsp;&nbsp; // 1. if the JITCompilationStarted is on one of the skipping thread, avoid following steps.<BR>&nbsp;&nbsp;&nbsp; DWORD currentThreadId = GetCurrentThreadId();<BR>&nbsp;&nbsp;&nbsp; if (m_SkipJCHashTable-&gt;PLookup(currentThreadId))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return S_OK;</P>
<P>&nbsp;&nbsp;&nbsp; // create the ManagedStub object<BR>&nbsp;&nbsp;&nbsp; if (m_pIManagedStub==NULL) // if it is already created, no need to create twice<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateManagedStub, this, 0, &amp;dwThreadId);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// add the thread Id to skip pool so that JITCompilationStarted will&nbsp;do nothing on that thread.&nbsp;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SkipJCHashTable-&gt;SetAt(dwThreadId, 0);&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (hThread != NULL)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaitForSingleObject(hThread, INFINITE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle(hThread);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SkipJCHashTable-&gt;RemoveKey(dwThreadId);&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; }</P>
<P>....</P>
<P>&nbsp;&nbsp;&nbsp; ///////////////////////////////////////////////////////<BR>&nbsp;&nbsp;&nbsp; // try to define a managed dynamic method and get the dynamic method method token<BR>&nbsp;&nbsp;&nbsp; // prepare the parameters to be passed in<BR>&nbsp;&nbsp;&nbsp; PMYDATA pData = (PMYDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));</P>
<P>&nbsp;&nbsp;&nbsp; if( pData == NULL )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto exit;</P>
<P>&nbsp;&nbsp;&nbsp; pData-&gt;assemblyName = wszAssemblyName;<BR>&nbsp;&nbsp;&nbsp; pData-&gt;methodTk = tkMethod;<BR>&nbsp;&nbsp;&nbsp; pData-&gt;thisObj = this;</P>
<P>&nbsp;&nbsp;&nbsp; ProfilerPrintf("Working on asm %ws func %ws.", wszAssemblyName, wszFunctionName);<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ManagedPreStub, pData, 0, &amp;dwThreadId);<BR>&nbsp;&nbsp;&nbsp; m_SkipJCHashTable-&gt;SetAt(dwThreadId, 0);&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; if (hThread != NULL)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaitForSingleObject(hThread, INFINITE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle(hThread);<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; m_SkipJCHashTable-&gt;RemoveKey(dwThreadId);</P>
<P>&nbsp;&nbsp;&nbsp; // we free up the memory here instead of in the thread because we want some return value back.<BR>&nbsp;&nbsp;&nbsp; wchar_t wszDelegateName[512];</P>
<P>&nbsp;&nbsp;&nbsp; if (pData-&gt;delegateName == NULL)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return S_OK;<BR>&nbsp;&nbsp;&nbsp; // copy the return value out<BR>&nbsp;&nbsp;&nbsp; wcsncpy_s(wszDelegateName, _countof(pData-&gt;delegateName), pData-&gt;delegateName, _countof(pData-&gt;delegateName));</P>
<P>&nbsp;&nbsp;&nbsp; HeapFree(GetProcessHeap(), 0, pData);</P>
<P>...</P>
<P>We have these definitions in ProfilerCallback.h:</P>
<P>private:</P>
<P>&nbsp;&nbsp;&nbsp; CMap&lt;DWORD, DWORD, int, int&gt; * m_SkipJCHashTable;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...</P>
<P>&nbsp;&nbsp;&nbsp; Enjoy!</P>
<P>&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>CLR Profiling API</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/clr-profiling-api</link>
      <pubDate>Wed, 28 Sep 2005 17:50:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/09/28/clr-profiling-api/</guid>
      <description><![CDATA[I think CLR Profiling API is one of the coolest things in CLR. Here is a nice article I just found...]]></description>
      <content:encoded><![CDATA[<P>I think CLR Profiling API is one of the coolest things in CLR. Here is a nice <A href="https://msdn.microsoft.com/msdnmag/issues/05/01/CLRProfiler/default.aspx">article</A> I just found on msdn about Whidbey Profiling APIs. Note that Everett Profiling API and Whidbey Profiling API are completely not compatible. You have to explicitly implement ICorProfilerCallback2 interface to make profiling work on Whidbey.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></P>
<P>Profiling provides the possibility&nbsp;to do&nbsp;runtime tracking, tracing and assembly rewriting. It is exactly what a tester would like to do in many aspects to test managed projects. <o:p></o:p></P>
<P>In order to show some ideas behind this, I will introduce one of our test tools here. <o:p></o:p></P>
<P>We implemented a Just-In-Time LCG converter tool based on Profiling API's ability to do method instrument. It was always a headache to test LCG because it is a new kind of method, completely dynamic, and touches nearly every aspect of the runtime. The only way to test it well is to leverage our existing tests which already covered nearly all aspects of CLR.<o:p></o:p></P>
<P>We implemented a DynMethodConverter tool based on Reflection. The tool loads the assembly and based on the methodinfos, it converts them to the dynamic methods, linked them up and invoke on the entry point. Everything looked good at the beginning but we came to many dead problems. The tool only worked on simple, verifiable test libraries. Tests with unmanaged entry points (interop tests, hosting tests), unsafe tests (cannot pass security checks while loading) and tests with drivers will have a difficult time to be adopted under the tool. <o:p></o:p></P>
<P>Then we looked at the possibility of solving this problem using Profiling API.<o:p></o:p></P>
<P>When the profiling is turned on, the JITCompliationStarted function gets called. We took that chance to change the method body to call on a DynamicMethod delegate. One tricky part is that LCG has to be created in managed code and Profiling API cannot have any managed stack on top of it. We worked around this issue by starting another thread in the JITCompilationStarted function; invoke managed code that will create the dynamic method there. We also cached that thread id in a global hashtable, so that when that managed code hits JITCompilationStarted function again, we can quickly know that we will have to do nothing there. On the managed side, it will be very natural to use token resolution APIs to get the calling method and leverage all the Reflection structures to create a dynamic method.<o:p></o:p></P>
<P>This tool can be very easily adapted to the automatic testing environment. We only need to turn the profiler on and off, register the necessary managed assembly as needed. It also solved all the previous limitations of tools based on Reflection. <o:p></o:p></P>
<P>Hope this sample helps you when you are designing your testing tool.<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p></P>
<P>&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>Something about ReflectionOnly Context</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/something-about-reflectiononly-context</link>
      <pubDate>Wed, 14 Sep 2005 14:17:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/09/14/something-about-reflectiononly-context/</guid>
      <description><![CDATA[I&nbsp;was reading&nbsp;Joel's blog about new stuff in Reflection and he mentioned ReflectionOnly...]]></description>
      <content:encoded><![CDATA[<P>I&nbsp;was reading&nbsp;<a href="https://blogs.msdn.com/joelpob/archive/2004/06/22/163206.aspx">Joel's blog</A> about new stuff in Reflection and he mentioned ReflectionOnly context. Apart from the Generics, token handle resolutions, LCG, ReflectionOnly context (actually a loader feature) had a big impact in Reflection area in Whidbey. It reminds me to talk about ReflectionOnly context thing in detail in my blog.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></P>
<P>ReflectionOnly context is first of all a loader concept, and here is <a href="https://blogs.msdn.com/junfeng/archive/2004/08/24/219691.aspx">Junfeng's blog entry</A> explaining that aspect in detail. <o:p></o:p></P>
<P>ReflectionOnly context's impact on Reflection is also large. Basically, Reflection can be summarized into two usages: inspect the assembly metadata and do latebind invocations. ReflectionOnly context is targeted for the first scenario *only*. <o:p></o:p></P>
<P>All&nbsp;those APIs related to execution is disabled (throws InvalidOperationException) if the assembly is loaded in a ReflectionOnly context. Those APIs are xxx.Invoke, FieldInfo.GetField, FieldInfo.SetField ... Their changes&nbsp;seem to be apparent and need no explanation. <o:p></o:p></P>
<P>There&nbsp;are several more APIs that are affected&nbsp;by ReflectionOnly context that do need some explanations:<o:p></o:p></P>
<UL type=disc>
<LI class=MsoNormal style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo1; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">GetCustomAttribute: The reason we have to disable this because GetCustomAttribute returns you an Attribute and to get that, we have to run the Attribute ctor. To enable the ReflectionOnly GetCustomAttribute, we provided a new API called GetCustomAttributeData that returns a CustomAttributeData object. That object contains the constructorinfo and other raw info about the&nbsp;Attribute arguments. Our new document contains detailed explanation on that type. Currently, GetCustomAttributeData performs close to GetCustomAttribute, but&nbsp;it doesn’t execute&nbsp;the ctor.&nbsp;It is possible that in the furture, we could provide a even faster GetCustomAttributeData. <o:p></o:p></LI></UL>
<P>&nbsp;<o:p></o:p></P>
<UL type=disc>
<LI class=MsoNormal style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l2 level1 lfo2; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">Handle related APIs: We disable all access to handles.&nbsp;Handle&nbsp;is really a runtime concept, it exists in the runtime and is used for invocation operations. By disabling handle access and usage&nbsp;in ReflectionOnly context, we basically guarded ourselves against many potential areas that could hack through the system trying to do invocation in ReflectionOnly context. On the other hand, we&nbsp;are able to do all the assembly inspection work without handles. All token APIs not related to Handle&nbsp;function in ReflectionOnly context. In the ReflectionOnly context, it is possible to build your reflector that prints out assembly content together with the methodbody. <o:p></o:p></LI></UL>
<P>&nbsp;<o:p></o:p></P>
<UL type=disc>
<LI class=MsoNormal style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l0 level1 lfo3; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">You may see there&nbsp;are new APIs called GetRawConstantValue on FieldInfo, PropertyInfo and ParameterInfo(GetRawDefaultValue). The usage of&nbsp;those APIs&nbsp;is to get the values encoded in the metadata out, which is supported in ReflectionOnly context. Particularly, if the field constant value is&nbsp;an enum,&nbsp;normal GetValue will try to return a enum and fail to execute the constructor, but GetRawConstantValue will return the encoded raw integer back to you. You should use GetRaw* APIs only when you are in ReflectionOnly context.<o:p></o:p></LI></UL>
<P>ReflectionOnly context is&nbsp;needed&nbsp;for certain scenarios to work. For example, you are developing a managed build tool such as regasm.exe that is supposed to work on all platforms. If you build the tool based on normal context, the tool will have difficulty to build a&nbsp;64 bit app on&nbsp;32 bit platform since we cannot load a 64 bit app on 32 bit platform in normal context.&nbsp;This scenario is common for build tools&nbsp;since in many places, people build their 64 bit apps using 32 bit machines. It is quite fair to recommend using ReflectionOnly context if your app is using Reflection only for&nbsp;content inspection&nbsp;to avoid unnecessary limitations.<o:p></o:p></P>
<P>The cons of ReflectionOnly context is that you cannot do any execution if the assembly is loaded that way (but for many tools, inspect the content is all Reflection used for) and you have to build your own assembly resolver since the loader won't resolve the assembly references for you automatically. ReflectionOnly load can also be used to load some unverifiable&nbsp;assemblies that normal load will fail since it skipped a lot of verification steps that normal load needed to do to ensure safe execution.<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p></P>]]></content:encoded>
    </item>
    <item>
      <title>GetMethod limitation regarding Generics</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/getmethod-limitation-regarding-generics</link>
      <pubDate>Wed, 14 Sep 2005 13:46:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/09/14/getmethod-limitation-regarding-generics/</guid>
      <description><![CDATA[I've got several inquiry emails about this issue, so I think it is a good idea to publish the...]]></description>
      <content:encoded><![CDATA[<P>I've got several <SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-fareast-language: ZH-CN; mso-ansi-language: EN-US; mso-bidi-language: AR-SA">inquiry</SPAN> emails about this issue, so I think it is a good idea to publish the problem here. </P>
<P>Say we have:</P>
<P><FONT face="Courier New" size=2>public class Test</FONT></P>
<P><FONT face="Courier New" size=2>{<BR>&nbsp;&nbsp; public void Teste&lt;U&gt;(U teste, int i) { Console.WriteLine(teste);&nbsp;}</FONT></P>
<P><FONT face="Courier New" size=2>&nbsp;&nbsp; public void Teste&lt;U&gt; (U teste) { }</FONT></P>
<P><FONT face="Courier New" size=2>}</FONT></P>
<P>Is it possible to use GetMethod to get&nbsp;void Teste&lt;U&gt;(U teste, int i)out?</P>
<P>Unfortunately, the answer is there is no way for now to use only GetMethod to get the method before we know the type of U.&nbsp;&nbsp;It is a limitation in Reflection for Whidbey. </P>
<P>Here is a possible workaround for you, you can use GetMembers to minimize the methodinfo you have to retrieve.</P>
<P><FONT face="Courier New" size=2>using System;<BR>using System.Reflection;</FONT></P>
<P><FONT face="Courier New" size=2>public class Test<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;public void Teste&lt;U&gt;(U teste, int i) { Console.WriteLine(teste);&nbsp;}</P>
<P><FONT face="Courier New" size=2>&nbsp;&nbsp;&nbsp; public void Teste&lt;U&gt; (U teste) { }</FONT></P>
<P></FONT><FONT face="Courier New" size=2>&nbsp;&nbsp;&nbsp; public static void Main()<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MemberInfo[] mis = typeof(Test).GetMember("Teste*", BindingFlags.InvokeMethod|BindingFlags.Public|BindingFlags.Instance);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (mis.Length == 0) {Console.WriteLine("No Teste Methods"); return;}<BR></FONT></P>
<P><FONT face="Courier New" size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Type U = ((MethodInfo)mis[0]).GetGenericArguments()[0]; // assume we know the&nbsp;class structure above,&nbsp;for simplicity.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MethodInfo mInfo = typeof(Test).GetMethod("Teste", new Type[] { U, typeof(int) });</FONT></P>
<P><FONT face="Courier New" size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (mInfo.IsGenericMethod)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mInfo = mInfo.MakeGenericMethod(typeof(string));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mInfo.Invoke(new Test(), new object[] {&nbsp; "Test - calling generic method", 1 });<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp; }<BR>}</FONT><BR></P>
<P>&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>HaiboLuo's blog</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/haiboluos-blog</link>
      <pubDate>Tue, 13 Sep 2005 14:06:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/09/13/haiboluos-blog/</guid>
      <description><![CDATA[Our Reflection QA definitely&nbsp;knows a lot&nbsp;and he is now having a blog of his...]]></description>
      <content:encoded><![CDATA[<P>Our Reflection QA <SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-fareast-language: ZH-CN; mso-ansi-language: EN-US; mso-bidi-language: AR-SA">definitely</SPAN>&nbsp;knows a lot&nbsp;and he is now having a blog of his own:</P>
<P><a href="https://blogs.msdn.com/haibo_luo">https://blogs.msdn.com/haibo_luo</A></P>
<P>A little advertisement, I know he is going to have something cool coming up soon. Just keep an eye on it.</P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>Reflection.Emit is not ThreadSafe</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/reflection-emit-is-not-threadsafe</link>
      <pubDate>Tue, 13 Sep 2005 13:54:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/09/13/reflection-emit-is-not-threadsafe/</guid>
      <description><![CDATA[Users are not supposed to&nbsp;operate on&nbsp;same Reflection.Emit object on multiple threads....]]></description>
      <content:encoded><![CDATA[<P>Users are not supposed to&nbsp;operate on&nbsp;same Reflection.Emit object on multiple threads. Reflection.Emit Objects are&nbsp;*NOT* thread-safe. It is certainly OK to operate on different Reflection.Emit objects on different threads.</P>
<P>We have been discovering issues when users trying to do the first scenario and we are trying hard to make the program not to crash. :) But the correctness cannot be guaranteed. So be careful.</P>]]></content:encoded>
    </item>
    <item>
      <title>Unexpected TypeLoadException during Type Creation</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/unexpected-typeloadexception-during-type-creation</link>
      <pubDate>Mon, 11 Jul 2005 19:32:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/07/11/unexpected-typeloadexception-during-type-creation/</guid>
      <description><![CDATA[We have found some limitations in Reflection.Emit that you cannot emit types that can be compiled in...]]></description>
      <content:encoded><![CDATA[<P>We have found some limitations in Reflection.Emit that you cannot emit types that can be compiled in C# compiler. You are unlikely to hit it in&nbsp;daily emit job but if ever you met one:</P>
<P>public class E<BR>{<BR>&nbsp;&nbsp;&nbsp; public struct N1<BR>&nbsp;&nbsp;&nbsp; { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public E e;<BR>&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; public struct N2<BR>&nbsp;&nbsp;&nbsp; { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public N1 n1;<BR>&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; N2 n2;&nbsp;&nbsp;&nbsp; <BR>}<BR></P>
<P>There are two partial order functions that must be satisfied for ref.emit type loading to succeed and sometimes there is way to satisfy both rules. The order rules are:</P>
<P>1. All types of all struct fields must be loaded before the type (this one is necessary)<BR>2. All enclosing types of all field types must be loaded before the type (this one is not necessary but is artificially imposed by the ref.emit path through the loader)<BR></P>
<P>For rule 1 the orders are the subset of all orders where N1 is loaded before N2 and N2 is loaded before E which leaves us with only one:</P>
<P>N1 &gt; N2 &gt; E</P>
<P>For rule 2 the partial orders are the subset of all orders where E is loaded before N2 which leaves us with 2:</P>
<P>E &gt; N1 &gt; N2<BR>N1 &gt; E &gt; N2</P>
<P>But there is no intersection of these sets and so no way to create this assembly with ref.emit.</P>
<P>Of course,&nbsp;the early bound loader doesn't have the rule 2 restriction so there is a code path that will work but it is likely too much work to move reflection emit over to that code path. So at least for Whidbey, we will have to live with such restrictions. </P>
<P>However, it is possible that you&nbsp;could try to&nbsp;solve the TypeLoadException by hooking your own type resolver up to the <FONT color=#000000>AppDomain's TypeResolve event.</FONT><BR></P>]]></content:encoded>
    </item>
    <item>
      <title>Token Handle Resolution with Generics</title>
      <link>https://docs.microsoft.com/archive/blogs/yirutang/token-handle-resolution-with-generics</link>
      <pubDate>Mon, 04 Jul 2005 22:06:00 GMT</pubDate>
      <dc:creator><![CDATA[yirutang]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yirutang/2005/07/04/token-handle-resolution-with-generics/</guid>
      <description><![CDATA[In Whidbey, apart from the token handle resolution APIs I mentioned earlier, there are some...]]></description>
      <content:encoded><![CDATA[<P>In Whidbey, apart from the token handle resolution APIs I mentioned earlier, there are some overloads making these APIs look a bit more complicated. Again, I am using APIs related to MethodInfo as an representitive example:</P>
<P><FONT face="Courier New" color=#000000 size=2>Token -&gt; Info</FONT></P>
<P><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT face="Courier New" color=#000000 size=2>public class Module</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"></SPAN><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT color=#000000><FONT face="Courier New"><FONT size=2>{<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></FONT></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT color=#000000><FONT face="Courier New"><FONT size=2><SPAN style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>public MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)</FONT></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" color=#000000 size=2>}</FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><FONT face="Courier New" color=#000000 size=2>Handle-&gt;Info</FONT></SPAN><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"><FONT face="Courier New" color=#000000 size=2>&nbsp;</FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT color=#000000><FONT face="Courier New"><FONT size=2>public class MethodBase<o:p></o:p></FONT></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none; tab-stops: .5in center 166.85pt"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT color=#000000><FONT face="Courier New"><FONT size=2>{<SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><o:p></o:p></FONT></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT color=#000000><FONT face="Courier New"><FONT size=2><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><SPAN style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle, RuntimeTypeHandle declaringType)</SPAN></FONT></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" color=#000000 size=2>}</FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"><FONT color=#000000><FONT face="Courier New"><FONT size=2></FONT></FONT></FONT></SPAN></SPAN></SPAN></P></SPAN><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"><FONT face="Courier New" color=#000000 size=2>Token-&gt;Handle</FONT></SPAN></SPAN> 
<P></P><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA">
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT color=#000000><FONT face="Courier New"><FONT size=2>public class ModuleHandle<o:p></o:p></FONT></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT color=#000000><FONT face="Courier New"><FONT size=2>{<o:p></o:p></FONT></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"></SPAN></SPAN><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"><FONT face="Courier New" color=#000000 size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public RuntimeMethodHandle ResolveMethodHandle(int methodToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)</FONT></SPAN></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"><FONT face="Courier New" color=#000000 size=2>}</FONT></SPAN></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA">These APIs are used for Generic related method resolution. </SPAN></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"><EM>Let's talk about the Handle-&gt;Info resolution first.</EM></SPAN></SPAN></P><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA">
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT color=#000000><FONT face="Courier New"><FONT size=2>public class MethodBase<o:p></o:p></FONT></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none; tab-stops: .5in center 166.85pt"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><FONT color=#000000><FONT face="Courier New"><FONT size=2>{<SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><o:p></o:p></FONT></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT color=#000000><FONT face="Courier New"><FONT size=2><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'"><SPAN style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle, RuntimeTypeHandle declaringType)</SPAN></FONT></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" color=#000000 size=2>}</FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2></FONT>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">Here is a bascially concept of code sharing in Generics. Again, Joel has a nice <a href="https://blogs.msdn.com/joelpob/archive/2004/11/17/259224.aspx">article</A> about it and within that article there are useful resource links for further reading. We are just going to put it simple here.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">In Generics, Methods&nbsp; instantiated with reference type share the same body (they are represented by the same Method Desc). </P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">That is G&lt;String&gt;.M and G&lt;Object&gt;.M share the same Method Desc; C.M&lt;String&gt; and C.M&lt;Object&gt; share the same Method Desc as well. Since RuntimeMethodHandle is a pointer to the method desc, those two methods have the same RuntimeMethodHandle. How to resolve this handle back correctly? </P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">The good news is that the if M is&nbsp;a static method on G&lt;T&gt;, the runtime is able to know if it is a method for G&lt;String&gt; or G&lt;Object&gt; by some additional internal data structure. </P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">If M is the generic method, the runtime is also able to distinquish the two. So in those cases, the additional declaringtype info is not needed for the MethodInfo to be resolved back.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">The only case runtime will not be able to differenciate the two&nbsp;methods is when the M is inside G&lt;T&gt; and M is a instance method. Runtime depends on the this pointer's type to figure out the declaring type of the method. In our handle resolution API, we have to tell the runtime what the declaringType is. That's when the second argument is needed.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">So here is a bit interesting thing, if M is a instance method, if you emit such code</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">new G&lt;String&gt;.ctor</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">call G&lt;Object&gt;.M</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">C&lt;String&gt;.M will be called because the runtime figured the declaring type of the instance method through this pointer.&nbsp;Of course, runtime cannot be fooled if you pass in G&lt;int&gt; as the this pointer for G&lt;object&gt;.M, it&nbsp;won't pass the JIT verification.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">However if M is a static method, Runtime is clever enough to figure out the Handle is really about the G&lt;String&gt;.M or G&lt;Object&gt;.M since no "this" pointer will be passed in.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">One thing need to be noted is that, code sharing is kind of a implementation detail of CLR, you shouldn't be building a program that relies on say G&lt;String&gt;.M.MethodHandle == G&lt;Object&gt;.M.MethodHandle although this sharing is not likely to change. But maybe one day, we decide to share more (for example, share code with instantitions of same size&nbsp;value type) or share less. RuntimeMethodHandle really exposed a quite low level and raw notation of the runtime, and you should be careful when using it and use it in the right way (the way we promised to work). </P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><EM>Now what about tokens?</EM></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">Token is the disk represntation of all kinds of types, to learn about tokens, the best way is to write a C# program and open it in ildasm.exe.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2>public class G&lt;T&gt;&nbsp; /* type def G`1&lt;T&gt; 02000002*/<BR>{<BR>&nbsp;public void M(T t) /* method def M(!T t) 06000001*/<BR>&nbsp;{}<BR>}<BR>public class C<BR>{<BR>&nbsp;public static void GM&lt;T&gt;(T t) /* method def GM&lt;T&gt;(!!T t) !!T means a different generic parameter than !!T 06000003*/<BR>&nbsp;{}<BR>}<BR>public class Test<BR>{<BR>&nbsp;public static void Main()<BR>&nbsp;{<BR>&nbsp;&nbsp;G&lt;String&gt; gString = new G&lt;String&gt;();&nbsp;<BR>&nbsp;&nbsp;gString.M("Hehe"); /* method ref under type spec G`1&lt;string&gt;::M(!0)&nbsp; method ref 0a000005 type spec 1b000001*/<BR>&nbsp; C.GM&lt;String&gt;("Haha"); /*method spec C::GM&lt;string&gt;(!!0)&nbsp; 2b000001*/<BR>&nbsp;}<BR>}</FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2><FONT face="Times New Roman" size=3>This example illustrates some of the basic concept of different type tokens (def token, ref token, and spec token)</FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">in ildasm we use ! to distinquish different type parameters, !0 means it is instantiated with whatever is in !T, 0 is the type parameter index.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">In this example G&lt;T&gt;.M G&lt;String&gt;.M, C.GM&lt;String&gt; are all of different tokens. However the info-&gt;token API will only return you def tokens, which means:</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">G&lt;Object&gt;.M.MetadataToken will&nbsp;return&nbsp;the token for G&lt;!T&gt;.M</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">C.GM&lt;String&gt;.MetadataToken will&nbsp;return the token for C.GM&lt;!!T&gt;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">However, reflection was able to resolve the spec token or ref token under a spec token. For those cases to work, however, you will need to provide the "context" where the specific token lives in. The context is the calling method's generic argument (if any) and calling method's declaring type's generic argument (if any). If there is none, you can just pass in null to the two parameters.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">The reason why we need this API can be illustrated below.</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2>using System;<BR>using System.Reflection;</FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2>public class G1&lt;T&gt;<BR>{<BR>&nbsp;&nbsp;&nbsp; public void M()<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C.M&lt;T&gt;();<BR>&nbsp;&nbsp;&nbsp; }<BR>}<BR>public class G2&lt;V&gt;<BR>{<BR>&nbsp;&nbsp;&nbsp; public void M()<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C.M&lt;V&gt;();<BR>&nbsp;&nbsp;&nbsp; }<BR>}</FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2>public class C<BR>{<BR>&nbsp;&nbsp;&nbsp; public static void M&lt;Z&gt;() { }<BR>}&nbsp; </FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2></FONT>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2><FONT face="Times New Roman" size=3>if you compile this program and ildasm it, you will see there is only one Method Spec which says initiate the method M with the first type argument. </FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2><FONT face="Times New Roman" size=3></FONT></FONT>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">MethodSpec #1 (2b000001)<BR>&nbsp;Parent&nbsp;&nbsp; : 0x06000005<BR>&nbsp;&nbsp;CallCnvntn: [GENERICINST]<BR>&nbsp;&nbsp;1 Arguments<BR>&nbsp;&nbsp;&nbsp;Argument #1:&nbsp; Var!0</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><FONT face="Courier New" size=2><FONT face="Times New Roman" size=3>In the context of the first call of C.M&lt;T&gt; the instantiation should be T and in the second call, the right argument for M&lt;Z&gt; is V. From the metadata itself, we don't know which method it actually is and that's why the context is needed to understand that token.</FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">For furthur reading about tokens, the best source is the ECMA CIL specificiation:</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><A href="https://www.ecma-international.org/publications/standards/Ecma-335.htm">https://www.ecma-international.org/publications/standards/Ecma-335.htm</A></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none">Today, I am searching myself on google, however, this blog wasn't shown as the top hits. I guess it is because I didn't put my name Yiru Tang here. :) </P></SPAN></SPAN>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><SPAN style="mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Courier New'; mso-no-proof: yes"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 200%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-family: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"></SPAN></SPAN>&nbsp;</P>]]></content:encoded>
    </item>
  </channel>
</rss>