Подтвердить что ты не робот

Как работать с массивами с использованием отражения

Я пишу код проверки. Код будет принимать данные, переданные в веб-службу, и решить, может ли он выполнить действие, или вернуть сообщение вызывающему, что они пропустили некоторые поля и т.д.

У меня это в основном работает, кроме массивов. Я отмечаю свойства с атрибутом [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 });

    }
}

Итак, мне кажется, что первое, что я могу сказать, это массив. Но как тогда я могу узнать, сколько элементов в массиве?

4b9b3361

Ответ 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();
}