如何使用反射获得泛型类型的正确文本定义?

Jam*_*een 26 c# generics reflection

我正致力于代码生成,并遇到了泛型问题.这是导致我问题的"简化"版本.

Dictionary<string, DateTime> dictionary = new Dictionary<string, DateTime>();
string text = dictionary.GetType().FullName;
Run Code Online (Sandbox Code Playgroud)

使用上面的代码片段,其值text如下:

 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]]
Run Code Online (Sandbox Code Playgroud)

(添加了换行符以提高可读性.)

有没有办法type在不解析上面的字符串的情况下以不同的格式获取类型name()?我希望得到以下结果text:

System.Collections.Generic.Dictionary<System.String, System.DateTime>
Run Code Online (Sandbox Code Playgroud)

Jar*_*Par 29

没有内置的方法可以在.Net Framework中获得此表示.也就是因为没有办法让它变得正确.在C#样式语法中有许多不能表示的构造.例如,"<> foo"是IL中的有效类型名称,但不能用C#表示.

但是,如果您正在寻找一个非常好的解决方案,它可以很快地手工实施.以下解决方案适用于大多数情况.它不会处理

  1. 嵌套类型
  2. 非法的C#名称
  3. 几个其他场景

例:

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();
}
Run Code Online (Sandbox Code Playgroud)


blu*_*ish 21

由于@ LukeH的评论,一个好的和干净的选择是

using System;
using System.CodeDom;
using System.Collections.Generic;
using Microsoft.CSharp;
//...
private string GetFriendlyTypeName(Type type)
{
    using (var p = new CSharpCodeProvider())
    {
        var r = new CodeTypeReference(type);
        return p.GetTypeOutput(r);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 更好然后标记为答案(通用类的子类正确显示) (3认同)