다음을 통해 공유


TypeName Grammar

I was about to post another blog regarding to tokens and handles and generics, but our Reflection tester Haibo suggested me to talk a little about the TypeName Grammar that we added in Whidbey because a lot of external bugs are being reported on this issue. 

 

Let's start from a bug:

Type.GetType("System.Drawing.Font") returns null

 

We can get the type of System.Object through Type.GetType(“System.Object”) but why we cannot get the type of System.Drawing.Fone? It simply because all we know is to look up your executing assembly and mscorlib for the types specified with simple name and we couldn't find the type because System.Drawing.Font is in System.Drawing.dll.

You will have to pass in the type name plus the assembly name in order for us to load the assembly then look for the type in that asssembly.

 

To make your program robust and being able to always get the Type back, you should be using the type's AssemblyFullyQualifiedName to get the type back. The easiest way to know a the AssemblyFullQualifiedName is to call t.AssemblyFullyQualifiedName.

For example, System.Drawing.Font  type’s AFQN is:

System.Drawing.Font, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

 

The rule behind it is:

t.FullName + “,” + asm.FullName = t.AFQN

 

For Generic Types, things become more complicated. The simplest way is still to call t. AssemblyFullyQualifiedName to see what is the right string to be used in Type.GetType.

 

A simple Generic Type G<Object, String> ’s AQFN may look like this:

G`2[[System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

 

It looks pretty complicated but to break it up, it is reasonable.

We cannot use single “[“ because then we will not know when is the start of a new Generic Parameter (they are all commas).

Calling

Type.GetType(“G`2[[System.Object],[System.String]]”) will return you the type because in this case, G, System.Object and System.String all reside in the default look up scope. If any of these types are not in the excuting assembly or mscorlib, then you will have to specify the AQFN of that type.

In our case, all the following names will retrieve the type back for you.

 

G`2[[System.Object, mscorlib],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

G`2[[System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String]]

G`2[[System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

 

So what should be the G<Object, String>'s full name? According to the rule above, it should be:

G`2[[System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

 

This fullname does contain some assembly infomation which seem to be a little strange to some users. But that assembly infomation is about the Generic Arguments and not about the type itself. We need them because Generic Arguments in live in a different assembly as the Generic Type Definition.

 

If you want to use Type.GetType to get back G<object>, the string to use is G[[System.Object]]. Again double "[" here.

 

If you want to automatically compose/parse these type names on large scales without having the type first, we provided a set of TypeNameBuilder and TypeNameParser APIs through mscoree.tlb. You can consume them either in unmanaged code or from managed side through interop.

 

Here is a small sample of using the API from managed side:

 

Tlbimp mscoree.tlb /out=mscoree_me.dll

using System;

using System.Reflection;

using System.Runtime.InteropServices;

using mscoree_mm;

 

public class TypeNameBuilderAPITest

{

            public static void Main()

            {

                       

                        ITypeNameFactory tf = new TypeNameFactoryClass();

                        ITypeNameBuilder tb = tf.GetTypeNameBuilder();

 

                        tb.Clear();

                        tb.AddName("G");

                        tb.OpenGenericArguments();

                        tb.OpenGenericArgument();

                        tb.AddName("T");

                        tb.AddAssemblySpec("Asm");

                        tb.CloseGenericArgument();

                        tb.CloseGenericArguments();

                        tb.AddSzArray();

                        Console.WriteLine(tb.ToString());

                       

                        uint Epos = 0; // error position

                        ITypeName tn = tf.ParseTypeName(tb.ToString(), out Epos);

                        Console.WriteLine(tn.GetTypeArgumentCount());

}

}

 

Output:

G[[T, Asm]][]

1

 

The last note is that, for Type.GetType(String typeName) if the typeName is correct in the grammar but we cannot find the type, we will return null on this API. If the type name grammar is incorrect, ArgumentException will be thrown.

Comments

  • Anonymous
    August 21, 2005
    Type.GetType gives us the ability to get type back from a string. We pass a well-written type name string...

  • Anonymous
    August 21, 2005
    Type.GetType gives us the ability to get type back from a string. We pass a well-written type name string...

  • Anonymous
    August 21, 2005
    Type.GetType gives us the ability to get type back from a string. We pass a well-written type name string...

  • Anonymous
    August 21, 2005
    Type.GetType gives us the ability to get type back from a string. We pass a well-written type name string...

  • Anonymous
    August 21, 2005
    Type.GetType gives us the ability to get type back from a string. We pass a well-written type name string...

  • Anonymous
    August 21, 2005
    Type.GetType gives us the ability to get type back from a string. We pass a well-written type name string...

  • Anonymous
    August 21, 2005
    Type.GetType gives us the ability to get type back from a string. We pass a well-written type name string...

  • Anonymous
    May 31, 2006
    Best of the text i read about a problem.

  • Anonymous
    June 02, 2006
    We are wellocme to it's configuration.

  • Anonymous
    June 06, 2006
    Wellcome to the real world.

  • Anonymous
    June 29, 2006
    Asaspal. Memrano tu es besta. Amigo.

  • Anonymous
    July 04, 2006
    Your article is quite right, thanks.

  • Anonymous
    March 21, 2007
    PingBack from http://farazmahmood.wordpress.com/2007/03/21/typegettypestring/

  • Anonymous
    July 30, 2007
    PingBack from http://www.greggum.com/post/ActivatorCreateInstance.aspx

  • Anonymous
    July 30, 2007
    PingBack from http://www.greggum.com/post/ActivatorCreateInstance.aspx

  • Anonymous
    August 17, 2008
    PingBack from http://blog.codealchemist.com/?p=3