如果我写下如下内容:
var type = typeof(List<string>);
Console.WriteLine(type.Name);
它将会写入:
List`1
我想让它只写入:
List
我该如何做到这一点呢? 有没有更聪明的方法可以避免使用Substring或类似的字符串操作函数?
var type = typeof(List<string>);
Console.WriteLine(type.Name);
它将会写入:
List`1
我想让它只写入:
List
我该如何做到这一点呢? 有没有更聪明的方法可以避免使用Substring或类似的字符串操作函数?
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());
Regex.Replace(t.Name, @"\[.*\]", string.Empty);
- Rodrigo ReisList[string]
outer.inner[other.whatever]
IEnumerable[T0]
Dictionary[string:int]
Test here
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;
}
}
我能想到的最简单的方法是在C#6中,你可以这样做:
public static void Main(string[] args)
{
Console.WriteLine(nameof(List<int>));
Console.WriteLine(nameof(Dictionary<int, int>));
}
这将打印:
List
Dictionary
static void Main(string[] args)
{
Console.WriteLine(WhatIsMyType<IEnumerable<string>>());
Console.WriteLine(WhatIsMyType<List<int>>());
Console.WriteLine(WhatIsMyType<IList<int>>());
Console.WriteLine(WhatIsMyType<List<ContentBlob>>());
Console.WriteLine(WhatIsMyType<int[]>());
Console.WriteLine(WhatIsMyType<ContentBlob>());
Console.WriteLine(WhatIsMyType<Dictionary<string, Dictionary<int, int>>>());
}
public static string WhatIsMyType<T>()
{
return typeof(T).NameWithGenerics();
}
public static string NameWithGenerics(this Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type.IsArray)
return $"{type.GetElementType()?.Name}[]";
if (!type.IsGenericType)
return type.Name;
var name = type.GetGenericTypeDefinition().Name;
var index = name.IndexOf('`');
var newName = index == -1 ? name : name.Substring(0, index);
var list = type.GetGenericArguments().Select(NameWithGenerics).ToList();
return $"{newName}<{string.Join(",", list)}>";
}
示例输出:
IEnumerable<String>
List<Int32>
IList<Int32>
List<ContentBlob>
Int32[]
ContentBlob
Dictionary<String,Dictionary<Int32,Int32>>
using System;
namespace TODO
{
public static class TypeExtensions
{
/// <summary>
/// From: https://dev59.com/Amw15IYBdhLWcg3wzO9_#6386234
/// </summary>
public static string GetNameWithoutGenericArity(this Type t)
{
string name = t.Name;
int index = name.IndexOf('`');
return index == -1 ? name : name.Substring(0, index);
}
public static string GetFullNameWithoutGenericArity(this Type t)
{
var result = $"{t.Namespace}.{t.GetNameWithoutGenericArity()}";
return result;
}
}
}
nameof(List<string>)
来完成此操作。 - Nick Strupat