c# - GetType 返回 Int 而不是 System.Int32

标签 c# .net reflection

GetType().ToString() 返回对象的全名。我想要您通常用来实例化该对象的名称,即 int 而不是 Int32。有没有办法做到这一点?

最佳答案

C# 有许多“类型”,它们实际上是 .NET CLR 的关键字别名 Type秒。在这种情况下,intSystem.Int32 的 C# 别名,但对于其他 C# 类型也是如此,例如 string这是 System.String 的别名.

这意味着当您深入了解反射并开始查看 CLR Type 时您找不到的元素 int , string或任何其他 C# 类型别名,因为 .NET 和 CLR 不知道它们......也不应该知道它们。

如果您想将 CLR 类型转换为 C# 别名,您必须自己通过查找来完成。像这样:

// This is the set of types from the C# keyword list.
static Dictionary<Type, string> _typeAlias = new Dictionary<Type, string>
{
    { typeof(bool), "bool" },
    { typeof(byte), "byte" },
    { typeof(char), "char" },
    { typeof(decimal), "decimal" },
    { typeof(double), "double" },
    { typeof(float), "float" },
    { typeof(int), "int" },
    { typeof(long), "long" },
    { typeof(object), "object" },
    { typeof(sbyte), "sbyte" },
    { typeof(short), "short" },
    { typeof(string), "string" },
    { typeof(uint), "uint" },
    { typeof(ulong), "ulong" },
    // Yes, this is an odd one.  Technically it's a type though.
    { typeof(void), "void" }
};

static string TypeNameOrAlias(Type type)
{
    // Lookup alias for type
    if (_typeAlias.TryGetValue(type, out string alias))
        return alias;

    // Default to CLR type name
    return type.Name;
}

对于可以正常工作的简单类型。泛型、数组和 Nullable需要更多的工作。数组和 Nullable值是这样递归处理的:

static string TypeNameOrAlias(Type type)
{
    // Handle nullable value types
    var nullbase = Nullable.GetUnderlyingType(type);
    if (nullbase != null)
        return TypeNameOrAlias(nullbase) + "?";

    // Handle arrays
    if (type.BaseType == typeof(System.Array))
        return TypeNameOrAlias(type.GetElementType()) + "[]";

    // Lookup alias for type
    if (_typeAlias.TryGetValue(type, out string alias))
        return alias;

    // Default to CLR type name
    return type.Name;
}

这将处理如下事情:

Console.WriteLine(TypeNameOrAlias(typeof(int?[][])));

泛型,如果你需要的话,基本上涉及相同的过程。扫描通用参数列表并在整个过程中递归地运行类型。


嵌套类型

当你运行 TypeNameOrAlias在嵌套类型上,结果只是特定类型的名称,而不是您需要指定的完整路径,以便从声明它的类型外部使用它:

public class Outer
{
    public class Inner
    {
    }
}
// TypeNameOrAlias(typeof(Outer.Inner)) == "Inner"

这解决了问题:

static string GetTypeName(Type type)
{
    string name = TypeNameOrAlias(type);
    if (type.DeclaringType is Type dec)
    {
        return $"{GetTypeName(dec)}.{name}";
    }
    return name;
}
// GetTypeName(typeof(Outer.Inner)) == "Outer.Inner"

泛型

.NET 类型系统中的泛型很有趣。处理类似 List<int> 的事情相对容易或 Dictionary<int, string>或类似的。将其插入 TypeNameOrAlias 的顶部:

    // Handle generic types
    if (type.IsGenericType)
    {
        string name = type.Name.Split('`').FirstOrDefault();
        IEnumerable<string> parms = 
            type.GetGenericArguments()
            .Select(a => type.IsConstructedGenericType ? TypeNameOrAlias(a) : a.Name);
        return $"{name}<{string.Join(",", parms)}>";
    }

现在您将获得关于 TypeNameOrAlias(typeof(Dictionary<int, string>)) 之类的正确结果等等。它还处理通用类型定义:TypeNameOrAlias(typeof(Dictionary<,>))将返回 Dictionary<TKey,TValue> .

当您将类嵌套在泛型中时,事情就会变得困难。尝试 GetTypeName(typeof(Dictionary<int, string>.KeyCollection))一个有趣的结果。

关于c# - GetType 返回 Int 而不是 System.Int32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56352299/

相关文章:

c# - 如何用rdlc中的新行替换定界符

c# - .NET/C# 将 IList<string> 绑定(bind)到 DataGridView

c# - 四舍五入到至少 2 到 4 位小数

.net - 使用 C# 创建 Windows 任务运行一次并立即删除

c# - 如何正确序列化自动生成的 WCF 类型

c# - 了解为什么在 Bot Builder Framework 示例 : MultiLingualBot 中似乎进行了三次翻译

c# - Selenium Webdriver c# 无需等待页面加载

c# - 在 Windows 应用商店应用程序中使用较旧的 dll (.NET)?

java - 使用 Java Polygons 进行反射和其他转换

Java 反射 getTypeParameters().length 返回 0