我需要以代碼中聲明的形式獲取泛型類型的名稱。使用C#反射獲取GenericType-Name良好格式
例如: 對於列表<的Int32 >我想串 「列表<的Int32 >」。 Standart屬性Type.Name在此情況下返回「List`1」。
編輯:例如固定
我需要以代碼中聲明的形式獲取泛型類型的名稱。使用C#反射獲取GenericType-Name良好格式
例如: 對於列表<的Int32 >我想串 「列表<的Int32 >」。 Standart屬性Type.Name在此情況下返回「List`1」。
編輯:例如固定
好吧,我已經做了一大堆的研究,發現的typeof(名單)具有「GetGenericArguments」,這將讓你的子名。所以,我會做這種方式(1種泛型類型,如果它是一個多它會採取一個循環類的東西。如果要求我可以發佈該功能。
下面是做到這一點的一個功能。多個通用參數,手柄「嵌套」泛型類型再次編輯,使這個使用聚合函數:
static string GetFullName(Type t)
{
if (!t.IsGenericType)
return t.Name;
StringBuilder sb=new StringBuilder();
sb.Append(t.Name.Substring(0, t.Name.LastIndexOf("`")));
sb.Append(t.GetGenericArguments().Aggregate("<",
delegate(string aggregate,Type type)
{
return aggregate + (aggregate == "<" ? "" : ",") + GetFullName(type);
}
));
sb.Append(">");
return sb.ToString();
}
嗯,這是因爲在.NET類型的名稱實際上是List'1。 「1」是泛型的所謂arity,它告訴你有多少個類型參數。
它的需要,這樣就可以創造更多的則1種泛型類型相同的「名字」,但不同數量的泛型類型參數。
例如,有超過1型「稱爲」 System.Action。這些真正的名字是System.Action'1,System.Action'2,System.Action'3等
所以,如果你知道你的類型是通用的,你可以假設這個'XX在名稱的結尾,因此您可以將此部分剪掉,例如:
string strTypeName = typeof(List<>).Name.Substring(0, typeof(List<>).Name.LastIndexOf("`"));
PS:請用'替換'。
對不起,在我的例子是錯誤的。我需要獲得泛型類型的參數(在我的示例中:Int32) – AndreyAkinshin 2009-10-07 18:06:40
此答案不再相關(在編輯問題之後)。 – ToolmakerSteve 2017-08-07 05:51:47
,是不是太硬;-)
好吧,我會咬.. 。克下一個工作recusively和顯示原始類型的w/o命名空間(如OP寫):
static string PrettyPrintGenericTypeName(Type typeRef)
{
var rootType = typeRef.IsGenericType
? typeRef.GetGenericTypeDefinition()
: typeRef;
var cleanedName = rootType.IsPrimitive
? rootType.Name
: rootType.ToString();
if (!typeRef.IsGenericType)
return cleanedName;
else
return cleanedName.Substring(0,
cleanedName.LastIndexOf('`'))
+ typeRef.GetGenericArguments()
.Aggregate("<",
(r, i) =>
r
+ (r != "<" ? ", " : null)
+ PrettyPrintGenericTypeName(i))
+ ">";
}
產生的cleanedName看起來是這樣的:System.Collections.Generic.Dictionary<System.Collections.Generic.List<Int32>, ConsoleApplication2.Program+SomeType>
使用內置的功能和LINQ這可以寫成
static string PrettyTypeName(Type t)
{
if (t.IsGenericType)
{
return string.Format(
"{0}<{1}>",
t.Name.Substring(0, t.Name.LastIndexOf("`", StringComparison.InvariantCulture)),
string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName)));
}
return t.Name;
}
注:在舊版本的C#,編譯器需要明確.ToArray()
:
string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName).ToArray()));
這應該是被接受的答案 – 2016-09-30 07:49:21
在VS 2010與.NET 3.5(不知道哪個C#版本),t.GetGenericArguments()。Select (PrettyTypeName)'給編譯器錯誤「*不能從'System.Collections.Generic.IEnumerable
另一個例子,我在這裏磕磕絆絆地寫了自己。
private string PrettyPrintGenericTypeName(Type p)
{
if (p.IsGenericType) {
var simpleName = p.Name.Substring(0, p.Name.IndexOf('`'));
var genericTypeParams = p.GenericTypeArguments.Select(PrettyPrintGenericTypeName).ToList();
return string.Format("{0}<{1}>", simpleName, string.Join(", ", genericTypeParams));
} else {
return p.Name;
}
}
老問題,但我今天只需要這個。所以我寫了一個擴展方法,可以輸出漂亮的C#格式的通用名稱,可以處理多層嵌套泛型類型。
using System;
using System.Text;
public static class TypeExtensions
{
public static string GetNiceName(this Type type, bool useFullName = false)
{
if (!type.IsGenericType) {
return type.Name;
}
var typeNameBuilder = new StringBuilder();
GetNiceGenericName(typeNameBuilder, type, useFullName);
return typeNameBuilder.ToString();
}
static void GetNiceGenericName(StringBuilder sb, Type type, bool useFullName)
{
if (!type.IsGenericType) {
sb.Append(useFullName ? type.FullName : type.Name);
return;
}
var typeDef = type.GetGenericTypeDefinition();
var typeName = useFullName ? typeDef.FullName : typeDef.Name;
sb.Append(typeName);
sb.Length -= typeName.Length - typeName.LastIndexOf('`');
sb.Append('<');
foreach (var typeArgument in type.GenericTypeArguments) {
GetNiceGenericName(sb, typeArgument, useFullName);
sb.Append(", ");
}
sb.Length -= 2;
sb.Append('>');
}
}
應該加強一點。泛型參數的格式應該是相同的,它可能是一個泛型類型。當然,它應該支持許多通用的論點。 – 2009-10-07 18:31:44
我正在輸入一個更復雜的版本來處理這個和多個,我剛剛發佈。 – Erich 2009-10-07 18:34:34
再次編輯以使用聚合。如果你想要'舊'版本,請檢查編輯歷史記錄。功能是相同的,但我想弄清楚如何彙總工作,這是一個很好的方式來學習:) – Erich 2009-10-07 18:51:52