type.IsGenericType
= true
时,我需要一些方法来获取类型的名称。
Type t = typeof(List<String>);
MessageBox.Show( ..?.. );
我想要的是一个弹出消息框List
,显示......我该怎么做?
答案 0 :(得分:53)
您可以实施一种扩展方法来获取友好名称&#34;一种类型,如:
public static class TypeNameExtensions
{
public static string GetFriendlyName(this Type type)
{
string friendlyName = type.Name;
if (type.IsGenericType)
{
int iBacktick = friendlyName.IndexOf('`');
if (iBacktick > 0)
{
friendlyName = friendlyName.Remove(iBacktick);
}
friendlyName += "<";
Type[] typeParameters = type.GetGenericArguments();
for (int i = 0; i < typeParameters.Length; ++i)
{
string typeParamName = GetFriendlyName(typeParameters[i]);
friendlyName += (i == 0 ? typeParamName : "," + typeParamName);
}
friendlyName += ">";
}
return friendlyName;
}
}
在项目中使用此功能,您现在可以说:
MessageBox.Show(t.GetFriendlyName());
它将显示&#34; List&lt; String&gt;&#34;。
我知道OP没有要求通用类型参数,但我更喜欢这种方式。 ; - )
命名空间,standard aliases for built-in types和StringBuilder的使用留给读者练习。 ; - )
答案 1 :(得分:32)
Type t = ...;
if (t.IsGenericType)
{
Type g = t.GetGenericTypeDefinition();
MessageBox.Show(g.Name); // displays "List`1"
MessageBox.Show(g.Name.Remove(g.Name.IndexOf('`'))); // displays "List"
}
答案 2 :(得分:16)
我对yoyo的看法。确保更原始的友好名称,处理数组,并递归处理嵌套泛型。还有单元测试。
{
"query" : {
"bool" : {
"must" : [
{ "match" : { "custom_query_rep" : "user" } },
{ "match" : { "custom_query_rep" : "abc" } }
]
}
}
}
答案 3 :(得分:8)
假设您只是想看到它需要List<T>
而不是List<string>
:
MessageBox.Show(t.GetGenericTypeDefinition().FullName)
请参阅http://msdn.microsoft.com/en-us/library/system.type.getgenerictypedefinition.aspx
答案 4 :(得分:6)
public static class TypeNameExtensions
{
public static string GetFriendlyName(this Type type)
{
var friendlyName = type.Name;
if (!type.IsGenericType) return friendlyName;
var iBacktick = friendlyName.IndexOf('`');
if (iBacktick > 0) friendlyName = friendlyName.Remove(iBacktick);
var genericParameters = type.GetGenericArguments().Select(x => x.GetFriendlyName());
friendlyName += "<" + string.Join(", ", genericParameters) + ">";
return friendlyName;
}
}
答案 5 :(得分:5)
这是我对此的看法。我没有进行反复检查,因为我看到它总是在那里。如果你愿意,你可以添加它,但我喜欢简单。
public static string GetFriendlyName(this Type type)
{
if (type.IsGenericType)
{
var name = type.Name.Substring(0, type.Name.IndexOf('`'));
var types = string.Join(",", type.GetGenericArguments().Select(GetFriendlyName));
return $"{name}<{types}>";
}
else
{
return type.Name;
}
}
答案 6 :(得分:3)
我在代码生成中使用了改进的yoyos版本。 请注意,现在所有类型都被引用为完全限定=&gt;全球:: System.String。
public static string GetFriendlyTypeName(Type type)
{
string friendlyName = type.Name;
if (type.IsGenericType)
{
int iBacktick = friendlyName.IndexOf('`');
if (iBacktick > 0)
{
friendlyName = friendlyName.Remove(iBacktick);
}
friendlyName += "<";
Type[] typeParameters = type.GetGenericArguments();
for (int i = 0; i < typeParameters.Length; ++i)
{
string typeParamName = GetFriendlyTypeName(typeParameters[i]);
friendlyName += (i == 0 ? typeParamName : "," + typeParamName);
}
friendlyName += ">";
friendlyName = "global::" + type.Namespace + "." + friendlyName;
}
else
{
friendlyName = "global::" + type.FullName;
}
return friendlyName.Replace('+', '.');
}
答案 7 :(得分:2)
这是一个基于先前答案的完整实现,同时支持别名(包括Nullable)和数组:
public static class TypeNameExtensions
{
public static string GetFriendlyName(this Type type, bool aliasNullable = true, bool includeSpaceAfterComma = true)
{
TryGetInnerElementType(ref type, out string arrayBrackets);
if (!TryGetNameAliasNonArray(type, out string friendlyName))
{
if (!type.IsGenericType)
{
friendlyName = type.Name;
}
else
{
if (aliasNullable && type.GetGenericTypeDefinition() == typeof(System.Nullable<>))
{
string generics = GetFriendlyName(type.GetGenericArguments()[0]);
friendlyName = generics + "?";
}
else
{
string generics = GetFriendlyGenericArguments(type, includeSpaceAfterComma);
int iBacktick = type.Name.IndexOf('`');
friendlyName = (iBacktick > 0 ? type.Name.Remove(iBacktick) : type.Name)
+ $"<{generics}>";
}
}
}
return friendlyName + arrayBrackets;
}
public static bool TryGetNameAlias(this Type type, out string alias)
{
TryGetInnerElementType(ref type, out string arrayBrackets);
if (!TryGetNameAliasNonArray(type, out alias))
return false;
alias += arrayBrackets;
return true;
}
private static string GetFriendlyGenericArguments(Type type, bool includeSpaceAfterComma)
=> string.Join(
includeSpaceAfterComma ? ", " : ",",
type.GetGenericArguments().Select(t => t.GetFriendlyName())
);
private static bool TryGetNameAliasNonArray(Type type, out string alias)
=> (alias = TypeAliases[(int)Type.GetTypeCode(type)]) != null
&& !type.IsEnum;
private static bool TryGetInnerElementType(ref Type type, out string arrayBrackets)
{
arrayBrackets = null;
if (!type.IsArray)
return false;
do
{
arrayBrackets += "[" + new string(',', type.GetArrayRank() - 1) + "]";
type = type.GetElementType();
}
while (type.IsArray);
return true;
}
private static readonly string[] TypeAliases = {
"void", // 0
null, // 1 (any other type)
"DBNull", // 2
"bool", // 3
"char", // 4
"sbyte", // 5
"byte", // 6
"short", // 7
"ushort", // 8
"int", // 9
"uint", // 10
"long", // 11
"ulong", // 12
"float", // 13
"double", // 14
"decimal", // 15
null, // 16 (DateTime)
null, // 17 (-undefined-)
"string", // 18
};
}
经过废话测试,例如:
var type = typeof(Dictionary<string[,], List<int?[,][]>[,,]>[]);
var name = type.GetFriendlyName();
Console.WriteLine(name);
它确实返回:"Dictionary<string[,], List<int?[,][]>[,,]>[]"
编辑:已更新,可以正确处理enum
类型。
答案 8 :(得分:1)
我知道这是一个古老的问题,但是我和一位同事以及我自己需要做一些智能感知/罗斯林工作。最佳解决方案似乎是Ali's解决方案,但不适用于嵌套类型:
int i = 1; //would work
List<string> listTest = new List<string>(); //would work
Dictionary<string, int> dictTest = new Dictionary<string, int>(); //would work
Dictionary<int, List<string>> nestTest = new Dictionary<int, List<string>>(); //would fail
Dictionary<int, List<Dictionary<string, List<object>>>> superNestTest = new Dictionary<int, List<Dictionary<string, List<object>>>>(); //would fail
Dictionary<int, List<Dictionary<string, int>>> superNestTest2 = new Dictionary<int, List<Dictionary<string, int>>>(); //would fail
为了解决这些问题,我将该函数转换为递归方法:
public static class TypeExtensions
{
public static string GetFriendlyName(this Type type)
{
string friendlyName = type.FullName;
if (type.IsGenericType)
{
friendlyName = GetTypeString(type);
}
return friendlyName;
}
private static string GetTypeString(Type type)
{
var t = type.AssemblyQualifiedName;
var output = new StringBuilder();
List<string> typeStrings = new List<string>();
int iAssyBackTick = t.IndexOf('`') + 1;
output.Append(t.Substring(0, iAssyBackTick - 1).Replace("[", string.Empty));
var genericTypes = type.GetGenericArguments();
foreach (var genType in genericTypes)
{
typeStrings.Add(genType.IsGenericType ? GetTypeString(genType) : genType.ToString());
}
output.Append($"<{string.Join(",", typeStrings)}>");
return output.ToString();
}
}
在前面的示例/测试用例中运行会产生以下输出:
System.Int32
System.Collections.Generic.List<System.String>
System.Collections.Generic.Dictionary<System.String,System.Int32>
System.Collections.Generic.Dictionary<System.Int32,System.Collections.Generic.List<System.String>>
System.Collections.Generic.Dictionary<System.Int32,System.Collections.Generic.List<System.Collections.Generic.Dictionary<System.String,System.Collections.Generic.List<System.Object>>>>
System.Collections.Generic.Dictionary<System.Int32,System.Collections.Generic.List<System.Collections.Generic.Dictionary<System.String,System.Int32>>>
我花了一些时间尝试解决嵌套类型问题,因此想在此处进行记录,以确保将来其他任何人都可以节省一些时间(和麻烦!)。我还检查了性能,它以毫秒为单位完成(在最后一种情况下为8毫秒:
效果结果
(原始方案列表中使用的变量名称)
"i" | 43uS
"listTest" | 3uS
"dictTest" | 2uS
"nestTest" | 5uS
"superNestTest" | 9uS
"superNestTest2" | 9uS
在每种情况下执行上述代码200次后的平均次数