确定泛型类型实例的泛型参数
如果你有泛型类型的实例但由于某种原因不知道特定类型,则可能需要确定用于创建此实例的泛型参数。
假设某人创建了 List<T>
的实例,并将其传递给方法:
var myList = new List<int>();
ShowGenericArguments(myList);
ShowGenericArguments
有这个签名:
public void ShowGenericArguments(object o)
所以在编译时你不知道使用了什么泛型参数来创建 o
。 Reflection 提供了许多检查泛型类型的方法。首先,我们可以确定 o
的类型是否是泛型类型:
public void ShowGenericArguments(object o)
{
if (o == null) return;
Type t = o.GetType();
if (!t.IsGenericType) return;
...
如果类型是泛型类型,则 Type.IsGenericType
返回 true
,如果不是,则返回 false
。
但这不是我们想知道的全部。List<>
本身也是一种通用类型。但我们只想检查特定构造泛型类型的实例。构造的泛型类型是例如具有特定类型 List<int>
参数用于其所有的通用参数。
Type
类提供了另外两个属性 IsConstructedGenericType
和 IsGenericTypeDefinition
,以区分这些构造的泛型类型和泛型类型定义:
typeof(List<>).IsGenericType // true
typeof(List<>).IsGenericTypeDefinition // true
typeof(List<>).IsConstructedGenericType// false
typeof(List<int>).IsGenericType // true
typeof(List<int>).IsGenericTypeDefinition // false
typeof(List<int>).IsConstructedGenericType// true
要枚举实例的泛型参数,我们可以使用 GetGenericArguments()
方法返回包含泛型类型参数的 Type
数组:
public void ShowGenericArguments(object o)
{
if (o == null) return;
Type t = o.GetType();
if (!t.IsConstructedGenericType) return;
foreach(Type genericTypeArgument in t.GetGenericArguments())
Console.WriteLine(genericTypeArgument.Name);
}
所以上面的调用(ShowGenericArguments(myList)
)会产生这样的输出:
Int32