是否有一种简单的方法,无需编写递归方法,从而为Type
类的泛型类型提供"用户友好"的名称?
。对于下面的代码,我想要类似于'List
var list = new List<Dictionary<int, string>>();
var type = list.GetType();
Console.WriteLine(type.Name);
Console.WriteLine(type.FullName);
根据您编辑的问题,您需要这样的内容:
public static string GetFriendlyName(this Type type)
{
if (type == typeof(int))
return "int";
else if (type == typeof(short))
return "short";
else if (type == typeof(byte))
return "byte";
else if (type == typeof(bool))
return "bool";
else if (type == typeof(long))
return "long";
else if (type == typeof(float))
return "float";
else if (type == typeof(double))
return "double";
else if (type == typeof(decimal))
return "decimal";
else if (type == typeof(string))
return "string";
else if (type.IsGenericType)
return type.Name.Split('`')[0] + "<" + string.Join(", ", type.GetGenericArguments().Select(x => GetFriendlyName(x)).ToArray()) + ">";
else
return type.Name;
}
您可以通过调用已经提供的递归方法来避免编写递归方法:
static string GetTypeName(Type type)
{
var codeDomProvider = CodeDomProvider.CreateProvider("C#");
var typeReferenceExpression = new CodeTypeReferenceExpression(new CodeTypeReference(type));
using (var writer = new StringWriter())
{
codeDomProvider.GenerateCodeFromExpression(typeReferenceExpression, writer, new CodeGeneratorOptions());
return writer.GetStringBuilder().ToString();
}
}
注意,这包括类型名称空间,但不包括程序集引用。对于问题中的类型,结果如下所示:
System.Collections.Generic.List<System.Collections.Generic.Dictionary<int, string>>
我不清楚这是否符合"类似"List<Dictionary<int, string>>
的条件。
当我需要解决方案时,我使用了以下代码:
public static string FriendlyName(this Type type)
{
if (type.IsGenericType)
{
var namePrefix = type.Name.Split(new [] {'`'}, StringSplitOptions.RemoveEmptyEntries)[0];
var genericParameters = type.GetGenericArguments().Select(FriendlyName).ToCsv();
return namePrefix + "<" + genericParameters + ">";
}
return type.Name;
}
和
public static string ToCsv(this IEnumerable<object> collectionToConvert, string separator = ", ")
{
return String.Join(separator, collectionToConvert.Select(o => o.ToString()));
}
使用例子:
var typeDisplayText = MyDataModel.GetType().FriendlyName();
…如果您正在创建自动生成的开发人员帮助页面,这也很有用,因为它包含通用参数名称:
public static string DefinitionTitle(this Type type)
{
if (type.IsGenericType)
{
var namePrefix = type.Name.Split(new[] { '`' }, StringSplitOptions.RemoveEmptyEntries)[0];
var genericParameters = type.GetGenericArguments().Select(a => a.Name).ToCsv();
return namePrefix + "<" + genericParameters + ">";
}
return type.Name;
}
使用例子:
var typeDefinitionText = typeof(Dictionary<,>).DefinitionTitle());
在Kirk的基础上建立一个更完整的答案是这样的。修改:
- 支持所有c#关键字支持custom-translations 数组
- 可空项为
ValueType?
而不是Nullable<ValueType>
完整代码:
public static class TypeTranslator
{
private static Dictionary<Type, string> _defaultDictionary = new Dictionary<System.Type, string>
{
{typeof(int), "int"},
{typeof(uint), "uint"},
{typeof(long), "long"},
{typeof(ulong), "ulong"},
{typeof(short), "short"},
{typeof(ushort), "ushort"},
{typeof(byte), "byte"},
{typeof(sbyte), "sbyte"},
{typeof(bool), "bool"},
{typeof(float), "float"},
{typeof(double), "double"},
{typeof(decimal), "decimal"},
{typeof(char), "char"},
{typeof(string), "string"},
{typeof(object), "object"},
{typeof(void), "void"}
};
public static string GetFriendlyName(this Type type, Dictionary<Type, string> translations)
{
if(translations.ContainsKey(type))
return translations[type];
else if (type.IsArray)
{
var rank = type.GetArrayRank();
var commas = rank > 1
? new string(',', rank - 1)
: "";
return GetFriendlyName(type.GetElementType(), translations) + $"[{commas}]";
}
else if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
return type.GetGenericArguments()[0].GetFriendlyName() + "?";
else if (type.IsGenericType)
return type.Name.Split('`')[0] + "<" + string.Join(", ", type.GetGenericArguments().Select(x => GetFriendlyName(x)).ToArray()) + ">";
else
return type.Name;
}
public static string GetFriendlyName(this Type type)
{
return type.GetFriendlyName(_defaultDictionary);
}
}
Reflection -从系统中获取泛型参数。
类型实例你也可以对泛型类型使用反射:
var dict = new Dictionary<string, int>();
Type type = dict.GetType();
Console.WriteLine("Type arguments:");
foreach (Type arg in type.GetGenericArguments())
{
Console.WriteLine(" {0}", arg);
}
你可以把它放到object的扩展方法中,并在任何你需要的地方使用它。我还想补充一点,每个递归都可以写成命令式代码。
所以整个代码看起来像:
static void GetGenericParametersNames(Type type)
{
Queue<Type> typeQueue = new Queue<Type>();
typeQueue.Enqueue(type);
while (typeQueue.Any())
{
var t = typeQueue.Dequeue();
Console.WriteLine(" {0}", arg);
foreach (Type arg in t.GetGenericArguments())
{
typeQueue.Enqueue(t);
}
}
}
使用GetDisplayName()
typeof(List<Dictionary<int, string>>).GetDisplayName()
会给你
"ListOfDictionaryOfIntegerAndString"