簡體   English   中英

通過反射從泛型類中的嵌套枚舉獲取枚舉值

[英]Get enum values via reflection from nested enum in generic class

我需要打印出我通過反射獲得的某些類型的枚舉值及其對應的下標值。 在大多數情況下,這都可以正常工作。 但是,如果在通用類型中聲明了枚舉,則Enum.GetValues會引發以下異常:

[System.NotSupportedException: Cannot create arrays of open type. ]  
at System.Array.InternalCreate(Void* elementType, Int32 rank, Int32* pLengths, Int32* pLowerBounds)    
at System.Array.CreateInstance(Type elementType, Int32 length)
at System.Array.UnsafeCreateInstance(Type elementType, Int32 length)   
at System.RuntimeType.GetEnumValues()

完整的復制代碼:

using System;

public class Program
{
    public static void Main()
    {
       var enumType= typeof(Foo<>.Bar);
       var underlyingType = Enum.GetUnderlyingType(enumType);
       Console.WriteLine(enumType.IsEnum);

       foreach(var value in Enum.GetValues(enumType))
       {
           Console.WriteLine("{0} = {1}", value, Convert.ChangeType(value, underlyingType));
       }
    }

}

public class Foo<T>
{
    public enum Bar
    {
        A = 1,
        B = 2
    }
}

在這里測試

這是理想的行為,我該如何工作?

構造一個類型將是一個麻煩的工作,但是對我來說是不可接受的,因為它將變得太復雜了。

構造類型將是一種解決方法,但對我來說是不可接受的,因為它會變得太復雜。

這是獲取將正常運行的值的唯一方法。

您可以使用開放類型的字段,而奇怪的是您可以通過這種方式獲取枚舉值。 您應該嘗試避免使用這些值,但是可以將它們轉換為它們的基礎類型。

public static void Main()
{
   var enumType = typeof(Foo<>.Bar);
   var underlyingType = Enum.GetUnderlyingType(enumType);

   foreach(var field in enumType.GetFields(BindingFlags.Public | BindingFlags.Static))
   {
       var value = field.GetValue(null);
       var underlyingValue = Convert.ChangeType(value, underlyingType);
       Console.WriteLine($"{field.Name} = {underlyingValue}");
   }
}

但是, 更好的解決方案是使用field.GetRawConstantValue()

public static void Main()
{
   var enumType = typeof(Foo<>.Bar);

   foreach(var field in enumType.GetFields(BindingFlags.Public | BindingFlags.Static))
   {
       Console.WriteLine($"{field.Name} = {field.GetRawConstantValue()}");
   }
}

這樣,如果將CLR固定為防止產生這種怪異的值,則您的代碼不會中斷。

這是預期的行為。 開放的泛型類型在運行時不能存在,因此它們內的任何內容也不能存在。 唯一的方法是先關閉任何類型的父類型,然后使用它來反映枚舉:

 var enumType = typeof(Foo<object>.Bar);

Foo是所謂的開放類型(由於其中包含泛型而未完全定義的類型),並且不允許使用開放類型數組,您可以通過執行以下操作來模擬它

Array.CreateInstance(typeof(Foo<>), 2)

並且由於Enum的GetValues依賴於創建數組,因此它失敗。 你可以做

var enumType = typeof(Foo<object>.Bar);

(“對象”是虛擬類型,因此您將無法使用開放類型)或執行Jon Skeet的建議。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM