Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the correct text definition of a generic type using reflection?

I am working on code generation and ran into a snag with generics. Here is a "simplified" version of what is causing me issues.

Dictionary<string, DateTime> dictionary = new Dictionary<string, DateTime>(); string text = dictionary.GetType().FullName; 

With the above code snippet the value of text is as follows:

 System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0,   Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.DateTime, mscorlib,   Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 

(Line breaks added for better readability.)

Is there a way to get the type name (type) in a different format without parsing the above string? I desire the following result for text:

System.Collections.Generic.Dictionary<System.String, System.DateTime> 
like image 561
Jamey McElveen Avatar asked Dec 30 '08 22:12

Jamey McElveen


People also ask

How do you find the type of generic type?

Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.

How do you call a generic using reflection?

You need to use reflection to get the method to start with, then "construct" it by supplying type arguments with MakeGenericMethod: MethodInfo method = typeof(Sample). GetMethod(nameof(Sample. GenericMethod)); MethodInfo generic = method.

How do you indicate that a class has a generic type parameter?

A generic type is declared by specifying a type parameter in an angle brackets after a type name, e.g. TypeName<T> where T is a type parameter.

How does a generic method differ from a generic type?

From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). A generic method differs from an ordinary method in the same way.


1 Answers

There is no built-in way to get this representation in the .Net Framework. Namely because there is no way to get it correct. There are a good number of constructs that are not representable in C# style syntax. For instance "<>foo" is a valid type name in IL but cannot be represented in C#.

However, if you're looking for a pretty good solution it can be hand implemented fairly quickly. The below solution will work for most situations. It will not handle

  1. Nested Types
  2. Illegal C# Names
  3. Couple of other scenarios

Example:

public static string GetFriendlyTypeName(Type type) {     if (type.IsGenericParameter)     {         return type.Name;     }      if (!type.IsGenericType)     {         return type.FullName;     }      var builder = new System.Text.StringBuilder();     var name = type.Name;     var index = name.IndexOf("`");     builder.AppendFormat("{0}.{1}", type.Namespace, name.Substring(0, index));     builder.Append('<');     var first = true;     foreach (var arg in type.GetGenericArguments())     {         if (!first)         {             builder.Append(',');         }         builder.Append(GetFriendlyTypeName(arg));         first = false;     }     builder.Append('>');     return builder.ToString(); } 
like image 171
JaredPar Avatar answered Oct 19 '22 17:10

JaredPar