此代碼應該適用於嵌套泛型類型(例如Foo<int>.Bar<string,object>
)。
public static string GetCSharpTypeName(this Type type, bool getFullName)
{
StringBuilder sb = new StringBuilder();
if (getFullName && !string.IsNullOrEmpty(type.Namespace))
{
sb.Append(type.Namespace);
sb.Append(".");
}
AppendCSharpTypeName(sb, type, getFullName);
return sb.ToString();
}
private static void AppendCSharpTypeName
(StringBuilder sb, Type type, bool fullParameterNames)
{
string typeName = type.Name;
Type declaringType = type.DeclaringType;
int declaringTypeArgumentCount = 0;
if (type.IsNested)
{
if (declaringType.IsGenericTypeDefinition)
{
declaringTypeArgumentCount =
declaringType.GetGenericArguments().Length;
declaringType = declaringType.MakeGenericType(
type.GetGenericArguments().Take(declaringTypeArgumentCount)
.ToArray());
}
AppendCSharpTypeName(sb, declaringType, fullParameterNames);
sb.Append(".");
}
Type[] genericArguments = type.GetGenericArguments()
.Skip(declaringTypeArgumentCount).ToArray();
int stopIndex;
if ((type.IsGenericTypeDefinition || type.IsGenericType)
&& ((stopIndex = type.Name.IndexOf('`')) > 0))
{
sb.Append(typeName.Substring(0, stopIndex));
string[] genericArgumentNames = genericArguments
.Select(t => GetCSharpTypeName(t, fullParameterNames)).ToArray();
if (genericArgumentNames.Length > 0)
sb.AppendFormat("<{0}>", string.Join(",", genericArgumentNames));
}
else
{
sb.Append(typeName);
}
}
很好的例子,很多潛在的特殊情況。有一點需要注意,genArgs上的for循環可以用一個字符串替代.Join(「,」,genArgs.Select(x => x.FullName)。如果速度存在差異,我的猜測是Marcs代碼可能會更快,但是我個人比較喜歡循環的可讀性 – 2009-06-05 09:18:02
,並使它們在功能上等同於選擇使用GetCSharpTypeName(T)而不是.FullName – 2009-06-05 09:18:54