我有以下代码:
return "[Inserted new " + typeof(T).ToString() + "]";
But
typeof(T).ToString()
返回包括命名空间在内的全名
是否有方法只获取类名(没有任何名称空间限定符?)
我有以下代码:
return "[Inserted new " + typeof(T).ToString() + "]";
But
typeof(T).ToString()
返回包括命名空间在内的全名
是否有方法只获取类名(没有任何名称空间限定符?)
typeof(T).Name // class name, no namespace
typeof(T).FullName // namespace and class name
typeof(T).Namespace // namespace, no class name
利用(类型属性)
Name Gets the name of the current member. (Inherited from MemberInfo.)
Example : typeof(T).Name;
尝试获取泛型类型的类型参数:
public static string CSharpName(this Type type)
{
var sb = new StringBuilder();
var name = type.Name;
if (!type.IsGenericType) return name;
sb.Append(name.Substring(0, name.IndexOf('`')));
sb.Append("<");
sb.Append(string.Join(", ", type.GetGenericArguments()
.Select(t => t.CSharpName())));
sb.Append(">");
return sb.ToString();
}
也许不是最好的解决方案(由于递归),但它是有效的。输出如下:
Dictionary<String, Object>
在c# 6.0(包括)之后,你可以使用nameof表达式:
using Stuff = Some.Cool.Functionality
class C {
static int Method1 (string x, int y) {}
static int Method1 (string x, string y) {}
int Method2 (int z) {}
string f<T>() => nameof(T);
}
var c = new C()
nameof(C) -> "C"
nameof(C.Method1) -> "Method1"
nameof(C.Method2) -> "Method2"
nameof(c.Method1) -> "Method1"
nameof(c.Method2) -> "Method2"
nameof(z) -> "z" // inside of Method2 ok, inside Method1 is a compiler error
nameof(Stuff) = "Stuff"
nameof(T) -> "T" // works inside of method but not in attributes on the method
nameof(f) -> “f”
nameof(f<T>) -> syntax error
nameof(f<>) -> syntax error
nameof(Method2()) -> error “This expression does not have a name”
注意!nameof不能获取底层对象的运行时类型,它只是编译时参数。如果一个方法接受一个IEnumerable对象,那么nameof简单地返回“IEnumerable”,而实际的对象可以是“List”。
下面的代码块在处理嵌套时生成类型名:
数组(T []) 泛型参数(即IEnumerable<T>)
此外,如果当前类型有可用的类型别名,它会尝试使用类型别名,这意味着会处理以下情况:
类型别名关键字(即System。字符串=> 可空类型别名(Nullable<T> => T?) ValueTuple别名,包括TRest嵌套(ValueTuple<T1, T2, T3, T4, T5, T6, T7, ValueTuple<T8, T9> => (T1, T2, T3, T4, T5, T6, T7, T8, T9))
代码如下:
public static class TypeExtensions
{
public static string GetFinalName(this Type type)
{
return GetFinalNameGenerator(type);
}
private static string GetFinalNameGenerator(Type type, bool parentIsTRest = false)
{
if (type.IsSZArray)
return $"{GetFinalNameGenerator(type.GetElementType())}[]";
if (!type.IsGenericType)
return TypeToAliasIfPossible(type);
if (type.GetGenericTypeDefinition() == typeof(Nullable<>))
return $"{GetGenericArgumentsDisplay(type)}?";
if (parentIsTRest || IsTupleAlias(type))
return ValueTupleToAlias(type, parentIsTRest);
return $"{type.Name[new Range(0, type.Name.IndexOf('`'))]}<{GetGenericArgumentsDisplay(type)}>";
}
private static string TypeToAliasIfPossible(Type type)
{
var typeAliasDict = new Dictionary<Type, string>
{
[typeof(bool)] = "bool",
[typeof(byte)] = "byte",
[typeof(sbyte)] = "sbyte",
[typeof(short)] = "short",
[typeof(ushort)] = "ushort",
[typeof(int)] = "int",
[typeof(uint)] = "uint",
[typeof(long)] = "long",
[typeof(ulong)] = "ulong",
[typeof(float)] = "float",
[typeof(double)] = "double",
[typeof(decimal)] = "decimal",
[typeof(char)] = "char",
[typeof(string)] = "string",
[typeof(object)] = "object",
[typeof(void)] = "void"
};
return typeAliasDict.GetValueOrDefault(type) ?? type.Name;
}
private static string GetGenericArgumentsDisplay(Type type)
{
return GetDisplay(type.GetGenericArguments());
}
private static string GetDisplay(IEnumerable<Type> genericArguments)
{
return string.Join(", ", genericArguments.Select(genericArgument => GetFinalNameGenerator(genericArgument)));
}
private static bool IsTupleAlias(Type type, bool parentIsTRest = false)
{
if (parentIsTRest && !type.IsGenericType)
return false;
var genericTypeDefinition = type.GetGenericTypeDefinition();
return genericTypeDefinition == typeof(ValueTuple<,>)
|| genericTypeDefinition == typeof(ValueTuple<,,>)
|| genericTypeDefinition == typeof(ValueTuple<,,,>)
|| genericTypeDefinition == typeof(ValueTuple<,,,,>)
|| genericTypeDefinition == typeof(ValueTuple<,,,,,>)
|| genericTypeDefinition == typeof(ValueTuple<,,,,,,>)
|| (parentIsTRest && genericTypeDefinition == typeof(ValueTuple<>))
|| (genericTypeDefinition == typeof(ValueTuple<,,,,,,,>) && IsTupleAlias(type.GetGenericArguments()[^1], true));
}
private static string ValueTupleToAlias(Type type, bool parentIsTRest)
{
var genericArguments = type.GetGenericArguments();
var valueTupleText = type.GetGenericTypeDefinition() != typeof(ValueTuple<,,,,,,,>)
? GetDisplay(genericArguments)
: $"{GetDisplay(genericArguments[new Range(0, ^1)])}, {GetFinalNameGenerator(genericArguments[^1], true)}";
return parentIsTRest
? valueTupleText
: $"({valueTupleText})";
}
}
用法很简单:
Console.WriteLine(typeof(Dictionary<string, IEnumerable<int?[][]>>).GetFinalName());
// Outputs: Dictionary<string, IEnumerable<int?[][]>>
如果你发现这个解决方案没有涵盖的任何边缘情况,请回复这篇文章,我会尝试更新答案。