Как работать с массивами с использованием отражения
Я пишу код проверки. Код будет принимать данные, переданные в веб-службу, и решить, может ли он выполнить действие, или вернуть сообщение вызывающему, что они пропустили некоторые поля и т.д.
У меня это в основном работает, кроме массивов. Я отмечаю свойства с атрибутом [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 });
}
}
Итак, мне кажется, что первое, что я могу сказать, это массив. Но как тогда я могу узнать, сколько элементов в массиве?
Ответы
Ответ 1
Во время выполнения объект будет динамически подклассифицирован из типа данных Array
(в этом подробном описании MSDN) t нужно отразить в массив, вы можете отбросить object
до Array
, а затем использовать метод экземпляра 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
.
Кстати, причина, по которой ваш код не работает, заключается в том, что вы не можете отличить массив от MyType[]
до object[]
, потому что object[]
не является базовым типом MyType[]
- только object
является.
Ответ 2
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
}
}
Ответ 3
Этот метод работает довольно хорошо, и это простой код.
var array = ((IEnumerable)propertyInfo.GetValue(instance)).Cast<object>().ToArray();
Ответ 4
Ответ с массивом хороший, но, как уже упоминалось, он не работает для некоторых других типов коллекций. Если вы не знаете, какой тип вашей коллекции пытается попробовать:
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();
}