2010-12-06 42 views
15

我正在使用反射來打印出方法簽名,例如如何獲取C#中的類型的原始名稱?

foreach (var pi in mi.GetParameters()) { 
    Console.WriteLine(pi.Name + ": " + pi.ParameterType.ToString()); 
} 

這工作得很好,但它打印出的圖元的類型爲「System.String」的而不是「串」和「[System.Int32] System.Nullable`1」,而不是「INT?」 。有沒有一種方法可以在代碼中查找參數的名稱,例如

public Example(string p1, int? p2) 

打印

p1: string 
p2: int? 

,而不是

p1: System.String 
p2: System.Nullable`1[System.Int32] 

回答

24

編輯:我是在下面的答案一半錯。

看看CSharpCodeProvider.GetTypeOutput。示例代碼:

using Microsoft.CSharp; 
using System; 
using System.CodeDom; 

class Test 
{ 
    static void Main() 
    { 
     var compiler = new CSharpCodeProvider(); 
     // Just to prove a point... 
     var type = new CodeTypeReference(typeof(Int32)); 
     Console.WriteLine(compiler.GetTypeOutput(type)); // Prints int 
    } 
} 

然而,這轉化成Nullable<T>T? - 我無法找到這將使它這樣做的任何選項,雖然這並不意味着這樣的選擇不存在:)


在框架中沒有什麼能夠支持這一點 - 畢竟它們是C#特有的名稱。

(注意string不是一個primitive type,順便說一句。)

你必須自己察覺Nullable`1做到這一點,並有來自全框架名給每個別名的地圖。

+0

難以等待您的更新:) – basarat 2010-12-06 18:45:47

+0

`雖然CSharpCodeProvider.GetTypeOutput`不會將`System.String`更改爲`string`。 – 2010-12-06 18:46:42

1

string只是表示System.String - string並不意味着幕後的任何事情。

順便說一句,得到過去System.Nullable'1[System.Int32],您可以使用Nullable.GetUnderlyingType(type);

0

這些都是問題的類型的實際名稱。 stringint?只是這些類型的C#別名。你必須自己做映射。

4

這個question有兩個有趣的答案。來自Jon Skeet的accepted one 幾乎說明了他已經說過的話。

編輯 喬恩更新了他的答案,所以它和我現在幾乎一樣。 (但當然20秒更早)

但盧克H也給了this answer,我認爲這是CodeDOM的非常棒的使用。

Type t = column.DataType; // Int64 

StringBuilder sb = new StringBuilder(); 
using (StringWriter sw = new StringWriter(sb)) 
{ 
    var expr = new CodeTypeReferenceExpression(t); 

    var prov = new CSharpCodeProvider(); 
    prov.GenerateCodeFromExpression(expr, sw, new CodeGeneratorOptions()); 
} 

Console.WriteLine(sb.ToString()); // long 
-3

這是我在約5分鐘的黑客攻擊後想出的。例如:

CSharpAmbiance.GetTypeName(typeof(IDictionary<string,int?>)) 

將返回System.Collections.Generic.IDictionary<string, int?>

public static class CSharpAmbiance 
{ 
    private static Dictionary<Type, string> aliases = 
     new Dictionary<Type, string>(); 

    static CSharpAmbiance() 
    { 
     aliases[typeof(byte)] = "byte"; 
     aliases[typeof(sbyte)] = "sbyte"; 
     aliases[typeof(short)] = "short"; 
     aliases[typeof(ushort)] = "ushort"; 
     aliases[typeof(int)] = "int"; 
     aliases[typeof(uint)] = "uint"; 
     aliases[typeof(long)] = "long"; 
     aliases[typeof(ulong)] = "ulong"; 
     aliases[typeof(char)] = "char"; 

     aliases[typeof(float)] = "float"; 
     aliases[typeof(double)] = "double"; 

     aliases[typeof(decimal)] = "decimal"; 

     aliases[typeof(bool)] = "bool"; 

     aliases[typeof(object)] = "object"; 
     aliases[typeof(string)] = "string"; 
    } 

    private static string RemoveGenericNamePart(string name) 
    { 
     int backtick = name.IndexOf('`'); 

     if (backtick != -1) 
      name = name.Substring(0, backtick); 

     return name; 
    } 

    public static string GetTypeName(Type type) 
    { 
     if (type == null) 
      throw new ArgumentNullException("type"); 

     string keyword; 
     if (aliases.TryGetValue(type, out keyword)) 
      return keyword; 

     if (type.IsArray) { 
      var sb = new StringBuilder(); 

      var ranks = new Queue<int>(); 
      do { 
       ranks.Enqueue(type.GetArrayRank() - 1); 
       type = type.GetElementType(); 
      } while (type.IsArray); 

      sb.Append(GetTypeName(type)); 

      while (ranks.Count != 0) { 
       sb.Append('['); 

       int rank = ranks.Dequeue(); 
       for (int i = 0; i < rank; i++) 
        sb.Append(','); 

       sb.Append(']'); 
      } 

      return sb.ToString(); 
     } 

     if (type.IsGenericTypeDefinition) { 
      var sb = new StringBuilder(); 

      sb.Append(RemoveGenericNamePart(type.FullName)); 
      sb.Append('<'); 

      var args = type.GetGenericArguments().Length - 1; 
      for (int i = 0; i < args; i++) 
       sb.Append(','); 

      sb.Append('>'); 

      return sb.ToString(); 
     } 

     if (type.IsGenericType) { 
      if (type.GetGenericTypeDefinition() == typeof(Nullable<>)) 
       return GetTypeName(type.GetGenericArguments()[0]) + "?"; 

      var sb = new StringBuilder(); 

      sb.Append(RemoveGenericNamePart(type.FullName)); 
      sb.Append('<'); 

      var args = type.GetGenericArguments(); 
      for (int i = 0; i < args.Length; i++) { 
       if (i != 0) 
        sb.Append(", "); 

       sb.Append(GetTypeName(args[i])); 
      } 

      sb.Append('>'); 

      return sb.ToString(); 
     } 

     return type.FullName; 
    } 
} 
1

不是最漂亮的代碼在世界上,但是這是我落得這樣做: (上Cornard代碼大樓)

public static string CSharpName(this Type type) 
{ 
    if (!type.FullName.StartsWith("System")) 
     return type.Name; 
    var compiler = new CSharpCodeProvider(); 
    var t = new CodeTypeReference(type); 
    var output = compiler.GetTypeOutput(t); 
    output = output.Replace("System.",""); 
    if (output.Contains("Nullable<")) 
     output = output.Replace("Nullable","").Replace(">","").Replace("<","") + "?"; 
    return output; 
} 
0

另一種選擇,基於這裏其他的答案。

特點:

  • 字符串轉換爲字符串的Int32與可空詮釋等
  • 新政的詮釋?等
  • 禁止System.DateTime的是日期時間
  • 所有其他類型都寫在全

它用簡單的情況下,我需要的,不知道這是否會處理複雜的類型以及涉及..

 Type type = /* Get a type reference somehow */ 
     if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 
     { 
      return compiler.GetTypeOutput(new CodeTypeReference(type.GetGenericArguments()[0])).Replace("System.","") + "?"; 
     } 
     else 
     { 
      return compiler.GetTypeOutput(new CodeTypeReference(type)).Replace("System.",""); 
     }  
相關問題