2010-12-06 3 views
15

Я использую отражение, чтобы распечатать подпись метода, например.Как я могу получить примитивное имя типа в C#?

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

Это работает довольно хорошо, но она выводит тип примитивов, как «System.String» вместо «строка» и «System.Nullable`1 [System.Int32]» вместо «межд?» , Есть ли способ получить имя параметра, как он выглядит в коде, например.

public Example(string p1, int? p2) 

печатает

p1: string 
p2: int? 

вместо

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

ответ

24

EDIT: Я был наполовину неправ в ответ ниже.

Посмотрите на 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

Таковы реальные имена типов в вопросе. string и int? - это просто псевдонимы C# для этих типов. Вы сами должны сделать картографирование.

4

У этого question есть два интересных ответа. accepted one от Jon Skeet в значительной степени говорит то, что он сказал уже.

EDIT Jon обновил свой ответ, чтобы его почти так же, как и у меня теперь. (Но, конечно, за 20 секунд раньше)

Но Luke 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 в целое и т.д.
  • сделки с Nullable в междунар? и т.д.
  • Подавить System.DateTime быть 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.",""); 
     }  
Смежные вопросы