对于使用反射创建控件的脚本,我需要区分
Int32
Int32?
List<string>
在.NET 4.5中,我可以使用
myType.IsConstructedGenericType
与
结合使用myType.IsValueType
并获取
但是, IsConstructedGenericType 在早期的.NET版本中不可用。我怎样才能在.NET 4.0中实现这一目标?
答案 0 :(得分:4)
您可以替换.IsGenericType && !.ContainsGenericParameters
。
问题是,这不会检测任何泛型类型参数本身是否为开放泛型类型(例如,在typeof(List<List<>>)
中),因此您需要使用{{3}递归执行此操作}。
这个示例代码应该可以工作,虽然我没有测试它并且不做任何保证:
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;
}
}
GetGenericArguments
的文档提供了有关此事的非常有用的信息。
答案 1 :(得分:1)
IsGenericType
将根据您提供的示例执行您想要的操作:
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);
}
}
不同之处在于使用IsConstructedGenericType
会为typeof(List<>)
返回false,而IsGenericType
将返回true。您可以使用Type.ContainsGenericParameters
在.NET 2 +中区分它们......虽然在病态情况下即使这样也不足 :
class Foo<T> : Dictionary<T, string> {}
考虑typeof(Foo<>).BaseType
:
IsConstructedGenericType
:True(它包含一个指定的类型参数)IsGenericType
:是的ContainsGenericParameters
:True(它仍然包含一个未分配的类型参数)希望这对您来说不是问题。