2012-09-07 52 views
3

我有一個方法讀取一些XML並填充一個對象。這是通過基於XML中的元素名稱映射對象上的屬性名稱的反射完成的。這適用於基本的對象類型,但我努力與枚舉數組。所以我有一個PropertyInfo對象(讓我們調用它的屬性)爲我的枚舉數組屬性,我有一個字符串值(讓我們調用它的值)包含逗號分隔的數字代表枚舉值(例如「1,3,5」 )。通過反射填充一個枚舉數組

我曾嘗試:

property.SetValue(this, value.Split(',').Select(i => int.Parse(i)).ToArray(), null);

property.SetValue(this, value.Split(',').Select(i => Enum.ToObject(property.PropertyType.GetElementType(), int.Parse(i))).ToArray(), null);

,但沒有喜悅。在第一個代碼示例中,Select.ToArray的結果是一個int [],然後拋出一個分析錯誤。與第二個類似的情況,但Select.ToArray返回一個對象[],並再次拋出解析錯誤。

我想寫這個,就好像枚舉類型是未知的一樣。

任何想法?

+0

「但沒有快樂」 - 那麼你有兩種方法會發生什麼? –

+0

你用這段代碼得到了什麼?編譯錯誤?運行時錯誤?信息是什麼? –

+0

對不起,添加更多詳細信息。 – CeejeeB

回答

2

試試這個:

// create the enum values as object[] 
var values = value.Split(',') 
    .Select(i => Enum.Parse(property.PropertyType.GetElementType(), i)) 
    .ToArray() 

// create array of correct type 
Array array = (Array)Activator.CreateInstance(property.PropertyType, values.Length); 

// copy the object values to the array 
int i = 0; 
foreach(var value in values) 
{ 
    array.SetValue(value, i++); 
} 

// set the property 
property.SetValue(this, array, null) 

有可能是一個更簡單的方法,但關鍵是你創建正確類型的數組。

+0

這是行不通的。該數組將具有類型'object []'。編輯:你更新了它:) – porges

1

下面是如何「正確地」做到這一點。通過反射來處理數組有點難看:

// assume that property is an array of some enum 

var enumType = property.PropertyType.GetElementType(); 
var values = value.Split(','); 
var enumArray = Array.CreateInstance(enumType, values.Length); 
for (int i = 0; i < enumArray.Length; ++i) 
    enumArray.SetValue(Enum.Parse(enumType, values[i]), i); 

property.SetValue(x, enumArray); 

重點是您需要創建具有正確元素類型的數組。如果你只是使用ToArray,那麼最好的情況是你會得到int[],最壞的情況是object[]

可以實際設定的int[]陣列一個枚舉數組屬性(只要該枚舉具有int作爲其基礎類型)。這是你的第一個例子中只是輕微的改動,你並不需要提供第三個參數:

property.SetValue(x, value.Split(',').Select(i => int.Parse(i)).ToArray()); 

然而,陣列設置該屬性屆時將有「錯誤」的類型。我不確定這是否會導致任何問題,但如果您正在進行大量依賴運行時類型的反射,則可能遇到一些問題。 (這也如果你想解析命名枚舉值將無法正常工作。)

+0

這應該是正確的答案 - 謝謝! –

0

這樣做的另一種方法,使用通用方法:

public class Class2 
{ 
    public enum TestEnum 
    { 
     One = 1, 
     Two = 2, 
     Three = 3 
    } 

    public TestEnum[] TestValues { get; set; } 

    public static T[] ConvertToEnum<T>(IEnumerable<int> values) 
    { 
     return values 
      .Select(v => (T)Enum.ToObject(typeof(T), v)) 
      .ToArray(); 
    } 

    public void Test() 
    { 
     var property = this.GetType().GetProperty("TestValues"); 

     var value = "1,2,3"; 

     var convert = this.GetType() 
      .GetMethod("ConvertToEnum") 
      .MakeGenericMethod(property.PropertyType.GetElementType()); 

     var intValues = value.Split(',').Select(v => int.Parse(v)); 

     var result = convert.Invoke(null, new[] { intValues }); 

     property.SetValue(this, result, null); 
    } 
} 

主要的一點是使陣列創建更多可讀。獎勵:ConvertToEnum<T>方法可以在其他地方重新使用。