对于使用反射创建控件的脚本,我需要区分
- 标准值类型,如
Int32
- 基于上述类型的通用可空类型,例如
Int32?
- 其他通用类型,如
List<string>
在 .NET 4.5 中,我可以使用
myType.IsConstructedGenericType
结合
myType.IsValueType
并得到
- 假/真
- 真/真
- 真假
但是,IsConstructedGenericType在早期的 .NET 版本中不可用。如何在 .NET 4.0 中实现这一点?
你可以用.IsGenericType && !.ContainsGenericParameters
那个代替。
问题是这不会检测任何泛型类型参数本身是否是开放泛型类型(例如 in typeof(List<List<>>)
),因此您需要使用GetGenericArguments
.
此示例代码应该可以工作,尽管我没有对其进行测试并且不做任何保证:
public static class TypeExtensions {
public static bool IsConstructedGenericType(this Type t)
{
if (!t.IsGenericType || t.ContainsGenericParameters)
{
return false;
}
if (!t.GetGenericArguments().All(
a => !a.IsGenericType || a.IsConstructedGenericType()))
{
return false;
}
return true;
}
}
的文档IsGenericType
提供了有关此问题的非常有用的信息。
IsGenericType
will do what you want for the examples you've given:
using System;
using System.Collections.Generic;
using System.Reflection;
public class Test
{
static void Main()
{
ShowType(typeof(int));
ShowType(typeof(int?));
ShowType(typeof(List<string>));
}
static void ShowType(Type type)
{
Console.WriteLine("{0} / {1}", type.IsGenericType, type.IsValueType);
}
}
The difference is that using IsConstructedGenericType
would return false for typeof(List<>)
whereas IsGenericType
will return true. You can use Type.ContainsGenericParameters
to distinguish between them in .NET 2+... although even that's not quite enough, in pathological cases:
class Foo<T> : Dictionary<T, string> {}
Consider typeof(Foo<>).BaseType
:
IsConstructedGenericType
: True (it contains one assigned type parameter)IsGenericType
: TrueContainsGenericParameters
: True (it still contains one unassigned type parameter)Hopefully this won't be an issue for you.