2010-12-06 44 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.",""); 
     }  
相关问题