Как мне работать с массивами, используя отражение - PullRequest
17 голосов
/ 20 сентября 2010

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

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

    }
}

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

Ответы [ 4 ]

24 голосов
/ 20 сентября 2010

Во время выполнения объект будет динамически разделен на подклассы из типа данных Array ( этот раздел MSDN содержит подробности ), поэтому вам не нужно отражаться в массиве, вы можете привести 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 .

5 голосов
/ 15 января 2016

Этот метод работает довольно хорошо, и это простой код.

var array = ((IEnumerable)propertyInfo.GetValue(instance)).Cast<object>().ToArray();
4 голосов
/ 20 сентября 2010
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 голосов
/ 10 сентября 2014

Ответ с массивом хороший, но, как уже упоминалось, он не работает для некоторых других типов коллекций. Если вы не знаете, к какому типу относится ваша коллекция, попробуйте что-то вроде:

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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...