Как я могу получить примитивное имя типа в C #? - PullRequest
21 голосов
/ 06 декабря 2010

Я использую отражение, чтобы распечатать сигнатуру метода, например

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

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

public Example(string p1, int? p2)

печать

p1: string
p2: int?

вместо

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

Ответы [ 6 ]

32 голосов
/ 06 декабря 2010

РЕДАКТИРОВАТЬ: я был наполовину неправильно в ответе ниже.

Посмотрите на 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 не a примитивного типа , между прочим.)

Вам придется сделать это, заметив Nullable`1 самостоятельно, и иметькарта с полным именем фреймворка для каждого псевдонима.

4 голосов
/ 06 декабря 2010

Этот вопрос имеет два интересных ответа. принял один от Джона Скита в значительной степени говорит то, что он уже сказал.

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

Но Люк Х также дает этот ответ , который, как мне показалось, был довольно удивительным использованием 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
2 голосов
/ 25 февраля 2017

Не самый красивый код в мире, но это то, что я в итоге сделал: (основываясь на коде Корнарда)

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;
}
1 голос
/ 18 мая 2017

Еще один вариант, основанный на других ответах здесь.

Особенности:

  • Преобразование String в string и Int32 в int и т. Д.
  • Сделка с Nullable<Int32> как int? и т. Д.
  • Подавить System.DateTime, чтобы быть DateTime
  • Все другие типы записаны полностью

Он касается простых случаев, которые мне нужны, не уверен, если этохорошо справится со сложными типами ..

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.","");
}   
0 голосов
/ 06 декабря 2010

Вот что я придумал после ~ 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;
    }
}
0 голосов
/ 06 декабря 2010

Нет.string это просто представление System.String - string на самом деле ничего не значит за кадром.

Кстати, чтобы пройти System.Nullable'1[System.Int32], вы можете использовать Nullable.GetUnderlyingType(type);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...