GetType返回Int而不是System.Int32

时间:2019-05-29 02:28:46

标签: c# .net reflection

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

3 个答案:

答案 0 :(得分:2)

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

这意味着当您深入思考并开始查看CLR int对象时,您将找不到string// 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; } 或任何其他C#类型别名因为.NET和CLR不了解它们……也不应该。

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

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"

这可以解决问题:

List<int>

泛型

.NET类型系统中的泛型很有趣。处理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))

当您将类嵌套在泛型中时,会遇到困难的地方。尝试vector以获得有趣的结果。

答案 1 :(得分:1)

GetType().ToString().FromDotNetTypeToCSharpType();

使用下面的扩展方法。对于以下模板,我使用以下Microsoft参考提出了类似的建议:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/built-in-types-table

(可选)可以将布尔类型是否可为null传递给快捷方式可为null的语法。

    /// <summary>Converts a .Net type name to a C# type name. It will remove the "System." namespace, if present,</summary>
    public static string FromDotNetTypeToCSharpType(this string dotNetTypeName, bool isNull = false)
    {
        string cstype = "";
        string nullable = isNull ? "?" : "";
        string prefix = "System.";
        string typeName = dotNetTypeName.StartsWith(prefix) ? dotNetTypeName.Remove(0, prefix.Length) : dotNetTypeName;

        switch (typeName)
        {
            case "Boolean": cstype = "bool"; break;
            case "Byte":    cstype = "byte"; break;
            case "SByte":   cstype = "sbyte"; break;
            case "Char":    cstype = "char"; break;
            case "Decimal": cstype = "decimal"; break;
            case "Double":  cstype = "double"; break;
            case "Single":  cstype = "float"; break;
            case "Int32":   cstype = "int"; break;
            case "UInt32":  cstype = "uint"; break;
            case "Int64":   cstype = "long"; break;
            case "UInt64":  cstype = "ulong"; break;
            case "Object":  cstype = "object"; break;
            case "Int16":   cstype = "short"; break;
            case "UInt16":  cstype = "ushort"; break;
            case "String":  cstype = "string"; break;

            default: cstype = typeName; break; // do nothing
        }
        return $"{cstype}{nullable}";

    }

答案 2 :(得分:-1)

如果我在阅读您的要求和理解。我假设它返回的是类似System.String的东西,而不仅仅是String。因此,有一种方法可以做到这一点。

        string someString = "Some String Value";

        //This is one quick and dirty way of mapping your returned value.
        someString = someString.GetType().ToString().Substring(7);

        Console.WriteLine("The variable type is {0}", someString);

如果想要“通用”选项,则基本上想要执行类似的操作。这应该做您想要的。但是请记住,如果它返回类似Int32的内容,那将是它的样子,而不仅仅是“ Int”。

        //Alternatively you can just do something like this. 
        Console.WriteLine(someString.GetType().Name); //Returns just "String"

要进行映射,只需使用条件和变量进行重新分配。

        //Your mapping would be done with this.
        if (someString.GetType().Name.ToUpper() == "INT32")
        {
            someString = "Int";
        }
        else if (someString.GetType().Name.ToUpper() == "STRING")
        {
            someString = "String";
        }