2010-09-19 84 views
12

我正在寫一些驗證代碼。該代碼將傳遞到Web服務數據,並決定是否可以做的動作,或返回一個消息,他們已經錯過了一些領域等如何處理數組使用反射

我除了陣列它主要的工作調用者。我使用[RequiredField]屬性標記屬性來表示所需的字段。所以,如果這是我的一些數據,

public enum EnumTest 
{ 
    Value1, 
    Value2 
} 

[DataContract] 
public class DummyWebserviceData 
{ 
    [DataMember] 
    [RequiredField] 
    public EnumTest[] EnumTest{ get; set; } 

    [DataMember] 
    [RequiredField] 
    public DummyWebserviceData2[] ArrayOfData { get; set; } 
} 

[DataContract] 
public class DummyWebserviceData2 
{ 
    [DataMember] 
    [RequiredField] 
    public string FirstName { get; set;} 

    [DataMember] 
    [RequiredField] 
    public string LastName { get; set;} 

    [DataMember] 
    public string Description { get; set;} 
} 

那麼我有什麼工作?我有日期和字符串工作的驗證。它使用遞歸來達到數據所需的任何級別。

但是......那麼,關於這兩個數組那裏。首先是一系列枚舉。我想在這種情況下檢查數組是否爲空。

第二是DummyWebserviceData2值的陣列。我需要將每個值拉出來並單獨查看。

爲了簡化我寫它看起來像這樣的代碼,

foreach (PropertyInfo propertyInfo in data.GetType().GetProperties()) 
{ 
    if (propertyInfo.PropertyType.IsArray) 
    { 
     // this craps out 

     object[] array = (object[])propertyInfo.GetValue(data, new object[] { 0 }); 

    } 
} 

所以,在我看來,第一件事是,我可以告訴它是一個數組。但是,我怎麼能告訴陣列中有多少物品?

回答

19

在運行時,對象將被動態地從Array數據類型(this MSDN topic details that)的子類,因此不需要反映到陣列,可以施放到objectArray,然後使用Array.GetValue實例方法:

Array a = (Array)propertyInfo.GetValue(data); 
for(int i = 0; i< a.Length; i++) 
{ 
    object o = a.GetValue(i); 
} 

也可以迭代數組以及 - 由於從NET 2.0起:

在.NET Framework 2.0版中,Array類實現了System.Collections.Generic :: IList,System.Collections.Generic :: ICollection和System.Collections.Generic :: IEnumerable通用接口。

你不需要知道T,因爲從這些你可以得到一個IEnumerable;然後你可以使用Cast()操作,或者只是在object級別工作。

順便說一下,爲什麼你的代碼是不工作的原因是因爲你不能轉換爲object[]MyType[]一個數組,因爲object[]不是MyType[]基本類型 - 只有object是。

+0

請注意,您不能使用IList或ICollection接口實現修改數組內容 - 正如前面提到的MDSN主題所述 - 它們都會拋出「NotSupportedException」 – 2010-09-19 21:52:06

+1

正確。我研究並發現了上面提到的許多相同的東西。我所做的確保數組的秩是1,否則數組可能是Array [] []。儘管感謝您的幫助。非常感激。 – peter 2010-09-19 22:00:34

+2

對Cast()'建議+1。 'MyType [] a =((Array)propertyInfo.GetValue(data))。Cast ().ToArray();' – 2010-09-19 22:55:39

4
foreach (PropertyInfo propertyInfo in data.GetType().GetProperties()) 
{ 
    if (propertyInfo.PropertyType.IsArray) 
    { 
     // first get the array 
     object[] array = (object[])propertyInfo.GetValue(data) 

     // then find the length 
     int arrayLength = array.GetLength(0); 

     // now check if the length is > 0 

    } 
} 
+0

接近 - 但是這不會起作用,因爲'data'不是陣列,它是'與是數組的屬性object' - 的'propertyInfo'必須用於訪問數組第一 – 2010-09-19 21:50:02

+0

編輯糾正... – Clicktricity 2010-09-19 21:55:40

0

與陣列的答案是好的,但提到它並不適用於其他一些集合類型的工作。如果你不知道是嘗試一些喜歡什麼類型的您的收藏:

IEnumerable<object> a = (IEnumerable<object>)myPropInfo.GetValue(myResourceObject); 
// at least foreach now is available 
foreach (object o in a) 
{ 
    // get the value 
    string valueAsString = o.ToString(); 
} 
1

此方法效果相當好,這是簡單的代碼。

var array = ((IEnumerable)propertyInfo.GetValue(instance)).Cast<object>().ToArray();