Как я могу получить примитивное имя типа в С#?
Я использую отражение для печати сигнатуры метода, например.
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]
Ответы
Ответ 1
РЕДАКТИРОВАТЬ: В ответе ниже я был не прав.
Посмотрите 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?
- и я не могу найти никаких параметров, которые бы это сделали, хотя это не означает, что такой вариант не существует:)
В рамках этого не существует ничего, что могло бы поддержать это: ведь они являются именами, специфичными для С#.
(Обратите внимание, что string
не является примитивным типом, между прочим.)
Вам нужно сделать это, указав Nullable`1
самостоятельно и иметь карту из полного имени фрейма для каждого псевдонима.
Ответ 2
Этот вопрос содержит два интересных ответа. принят от Jon Skeet в значительной степени говорит то, что он сказал уже.Забастовкa >
ИЗМЕНИТЬ
Джон обновил свой ответ, так что он почти такой же, как мой. (Но, конечно, 20 секунд раньше)
Но Luke H также дает этот ответ, который, как я думал, был довольно устрашающим использованием 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
Ответ 3
Нет. string
- это просто представление System.String
- string
на самом деле не означает ничего за кулисами.
Кстати, чтобы пройти мимо System.Nullable'1[System.Int32]
, вы можете использовать Nullable.GetUnderlyingType(type);
Ответ 4
Не самый красивый код в мире, но это то, что я закончил:
(на основе кода Корнарда)
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;
}
Ответ 5
Это фактические имена типов, о которых идет речь. string
и int?
- это просто псевдонимы С# для этих типов. Вы сами должны сделать картографирование.
Ответ 6
Другой вариант, основанный на других ответах здесь.
Особенности:
- Преобразование String в строку и Int32 в int и т.д.
- Сделка с Nullable как int? и т.д.
- Подавить System.DateTime для DateTime
- Все остальные типы написаны полностью
Он имеет дело с простыми случаями, которые мне нужны, не уверен, хорошо ли он будет обрабатывать сложные типы.
Type type = /* Get a type reference somehow */
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.","");
}
Ответ 7
Вот что я придумал после ~ 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;
}
}