Получить имя типа без информации о дженериках
Если я пишу:
var type = typeof(List<string>);
Console.WriteLine(type.Name);
Он напишет:
List`1
Я хочу, чтобы он просто писал:
Список
Как я могу это сделать?
Есть ли более разумный способ сделать это, не используя Substring
или аналогичные функции манипуляции с строкой?
Ответы
Ответ 1
Нет, у него есть смысл включить в него общую арность - потому что это часть того, что делает имя уникальным (вместе с сборкой и пространством имен, конечно).
Поместите это так: System.Nullable
и System.Nullable<T>
- очень разные типы. Это не ожидало, что вы захотите смутить этих двух... поэтому, если вы хотите потерять информацию, вам придется работать, чтобы это сделать. Разумеется, это не очень сложно и может быть помещено в вспомогательный метод:
public static string GetNameWithoutGenericArity(this Type t)
{
string name = t.Name;
int index = name.IndexOf('`');
return index == -1 ? name : name.Substring(0, index);
}
Тогда:
var type = typeof(List<string>);
Console.WriteLine(type.GetNameWithoutGenericArity());
Ответ 2
Нет, это не так, потому что "generic-type-string" является частью имени типа.
Ответ 3
Если кому-то интересно, я создал несколько методов расширения для этой проблемы, которые создают более "читаемую" строку
он создает что-то вроде
List[string]
outer.inner[other.whatever]
IEnumerable[T0]
Dictionary[string:int]
Тест здесь
public static class TypeEx
{
public static string GetTypeName(this Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (!type.IsGenericType)
return type.GetNestedTypeName();
StringBuilder stringBuilder = new StringBuilder();
_buildClassNameRecursiv(type, stringBuilder);
return stringBuilder.ToString();
}
private static void _buildClassNameRecursiv(Type type, StringBuilder classNameBuilder, int genericParameterIndex = 0)
{
if (type.IsGenericParameter)
classNameBuilder.AppendFormat("T{0}", genericParameterIndex + 1);
else if (type.IsGenericType)
{
classNameBuilder.Append(GetNestedTypeName(type) + "[");
int subIndex = 0;
foreach (Type genericTypeArgument in type.GetGenericArguments())
{
if (subIndex > 0)
classNameBuilder.Append(":");
_buildClassNameRecursiv(genericTypeArgument, classNameBuilder, subIndex++);
}
classNameBuilder.Append("]");
}
else
classNameBuilder.Append(type.GetNestedTypeName());
}
public static string GetNestedTypeName(this Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (!type.IsNested)
return type.Name;
StringBuilder nestedName = new StringBuilder();
while(type != null)
{
if(nestedName.Length>0)
nestedName.Insert(0,'.');
nestedName.Insert(0, _getTypeName(type));
type = type.DeclaringType;
}
return nestedName.ToString();
}
private static string _getTypeName(Type type)
{
return type.IsGenericType ? type.Name.Split('`')[0]: type.Name;
}
}
Ответ 4
Console.WriteLine(type.GetGenericTypeDefinition().UnderlyingSystemType.Name)