確定泛型型別例項的泛型引數

如果你有泛型型別的例項但由於某種原因不知道特定型別,則可能需要確定用於建立此例項的泛型引數。

假設某人建立了 List<T> 的例項,並將其傳遞給方法:

var myList = new List<int>();
ShowGenericArguments(myList);

ShowGenericArguments 有這個簽名:

public void ShowGenericArguments(object o)

所以在編譯時你不知道使用了什麼泛型引數來建立 oReflection 提供了許多檢查泛型型別的方法。首先,我們可以確定 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 類提供了另外兩個屬性 IsConstructedGenericTypeIsGenericTypeDefinition ,以區分這些構造的泛型型別和泛型型別定義:

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