开发者

How can I get the primitive name of a type in C#?

开发者 https://www.devze.com 2023-01-29 07:29 出处:网络
I\'m using reflection to print out a method signature, e.g. foreach (var pi in mi.GetParameters()) { Console.WriteLine(pi.Name + \": \" + pi.ParameterType.ToString());

I'm using reflection to print out a method signature, e.g.

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

This works pretty well, but it prints out the type of primitives as "System.String" instead of "string" and "System.Nullable`1[System.Int32]" instead of "int?". Is there a way to get the name of the paramete开发者_开发技巧r as it looks in code, e.g.

public Example(string p1, int? p2)

prints

p1: string
p2: int?

instead of

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


EDIT: I was half wrong in the answer below.

Have a look at CSharpCodeProvider.GetTypeOutput. Sample code:

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
    }
}

However, this doesn't translate Nullable<T> into T? - and I can't find any options which would make it do so, although that doesn't mean such an option doesn't exist :)


There's nothing in the framework to support this - after all, they're C#-specific names.

(Note that string isn't a primitive type, by the way.)

You'll have to do it by spotting Nullable`1 yourself (Nullable.GetUnderlyingType may be used for this, for example), and have a map from the full framework name to each alias.


This question has two interesting answers. The accepted one from Jon Skeet pretty much says what he said already.

EDIT Jon updated his answer so its pretty much the same as mine is now. (But of course 20 secs earlier)

But Luke H also gives this answer which I thought was pretty awesome use of the 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


Not the most beautiful code in the world, but this is what I ended up doing: (building on Cornard's code)

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;
}


Another option, based on the other answers here.

Features:

  • Convert String to string and Int32 to int etc
  • Deal with Nullable<Int32> as int? etc
  • Suppress System.DateTime to be DateTime
  • All other types are written in full

It deals with the simple cases I needed, not sure if it will handle complex types well..

Type type = /* Get a type reference somehow */
var compiler = new CSharpCodeProvider();
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.","");
}   


No. string is just a representation of System.String -- string doesn't really mean anything behind the scenes.

By the way, to get past System.Nullable'1[System.Int32], you can use Nullable.GetUnderlyingType(type);


Here's what I came up with after ~5 mins of hacking. For example:

CSharpAmbiance.GetTypeName(typeof(IDictionary<string,int?>))

will return 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;
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消