Использование свойств чтения отражения объекта, содержащего массив другого объекта

Как я могу прочитать свойства объекта, который содержит элемент типа массива, используя отражение в С#. Если у меня есть метод с именем GetMyProperties, и я определяю, что объект является пользовательским типом, то как я могу прочитать свойства массива и значения внутри. IsCustomType — это метод для определения того, является ли тип пользовательским типом или нет.

public void GetMyProperties(object obj) 
{ 
    foreach (PropertyInfo pinfo in obj.GetType().GetProperties()) 
    { 
        if (!Helper.IsCustomType(pinfo.PropertyType)) 
        { 
            string s = pinfo.GetValue(obj, null).ToString(); 
            propArray.Add(s); 
        } 
        else 
        { 
            object o = pinfo.GetValue(obj, null); 
            GetMyProperties(o); 
        } 
    } 
}

Сценарий таков: у меня есть объект ArrayClass, а ArrayClass имеет два свойства:

-string Id
-DeptArray[] depts

DeptArray — это еще один класс с двумя свойствами:

-string code 
-string value

Итак, этот метод получает объект ArrayClass. Я хочу прочитать все свойства сверху вниз и сохранить пару имя/значение в элементе словаря/списка. Я могу сделать это для значения, пользовательского типа, типа перечисления. Я застрял с массивом объектов. Не знаю, как это сделать.


person Sri Reddy    schedule 02.02.2011    source источник
comment
Привет, я не вижу из вашего кода, чего вы пытаетесь достичь. Код не скомпилируется, потому что pInfo.GetValue возвращает объект, а не строку.   -  person Adam    schedule 02.02.2011
comment
Прошу прощения за это. Я отредактировал код, добавив ToString() в pInfo.GetValue(). Пришлось придумывать этот метод. Изначально метод имеет сложную логику. Чтобы упростить, мне нужно прочитать все свойства, свойство свойства и его значение.   -  person Sri Reddy    schedule 02.02.2011


Ответы (2)


Попробуйте этот код:

public static void GetMyProperties(object obj)
{
  foreach (PropertyInfo pinfo in obj.GetType().GetProperties())
  {
    var getMethod = pinfo.GetGetMethod();
    if (getMethod.ReturnType.IsArray)
    {
      var arrayObject = getMethod.Invoke(obj, null);
      foreach (object element in (Array) arrayObject)
      {
        foreach (PropertyInfo arrayObjPinfo in element.GetType().GetProperties())
        {
          Console.WriteLine(arrayObjPinfo.Name + ":" + arrayObjPinfo.GetGetMethod().Invoke(element, null).ToString());
        }
      }
    }
  }
}

Я протестировал этот код, и он правильно разрешает массивы посредством отражения.

person EvgK    schedule 02.02.2011
comment
@evgk, я не могу явно указать DeptArray. Я определяю тип во время выполнения. Параметр метода obj может иметь любой объект класса. Мне нужен общий метод для проверки массивов и перебора его элементов. - person Sri Reddy; 03.02.2011
comment
Или нет проблем, я изменил ответ. Теперь он получит все массивы в переданном объекте и будет перебирать каждый элемент массива и его свойства без явного приведения. Вы также можете сделать этот метод рекурсивным, если хотите. - person EvgK; 03.02.2011
comment
@Evgk, гениально! это идеально - спасибо, я проверю логику с различными свойствами объекта, чтобы увидеть, не сработает ли где-нибудь. Когда вы говорите рекурсивный, нужно ли проверять, есть ли в свойствах массива массив? - person Sri Reddy; 03.02.2011
comment
@EvgK, два дополнительных вопроса: 1. Как получить значения, если obj является строкой [] или int [] или массивом любого типа значений? obj.GetType().GetProperties() никогда ничего не возвращает. 2. Не подскажете, как изменить приведенный выше метод, принимающий параметр типа ParameterInfo.ParameterType вместо obj? Что мне тогда передать в getMethod.Invoke()? - person Sri Reddy; 05.02.2011
comment
1. Это не из-за типа значения, а из-за того, что тип int, например, вообще не имеет никаких свойств. Таким образом, вы должны просто использовать сам объект, не перечисляя его свойства (например, Console.WriteLine(element); - person EvgK; 07.02.2011
comment
2. Я не понимаю, что такое ParameterInfo.ParameterType. Пожалуйста, опишите подробнее. - person EvgK; 07.02.2011
comment
спасибо EvgK за объяснение. Мне удалось реализовать 1. Для 2 я планирую использовать вышеуказанный метод для отображения свойств параметров метода, а также использовать его для отображения свойств возвращаемого типа. Этот метод отлично работает для возвращаемых типов. Но чтобы отобразить все свойства для параметра метода, я хочу передать ParameterInfo.ParameterType, и он должен рекурсивно получить все свойства. Как вы думаете, я должен создать другую тему, чтобы объяснить это более подробно? Ваша помощь приветствуется! - person Sri Reddy; 07.02.2011
comment
Пытался понять, но мне все равно непонятно :) С чего начать? Возможно, вам действительно следует начать новую тему и предоставить нам сигнатуру метода, который вы хотите, и, возможно, какой-нибудь псевдокод, чтобы сделать его более понятным. - person EvgK; 07.02.2011
comment
Спасибо ЕвгК. Я начал новый поток stackoverflow.com/questions/4923995/. Если у вас есть возможность, пожалуйста, ответьте. - person Sri Reddy; 07.02.2011

Вам нужно будет получить объект значения свойства, а затем вызвать для него GetType(). Затем вы можете сделать что-то вроде этого:

var type = pinfo.GetGetMethod().Invoke(obj, new object[0]).GetType();
if (type.IsArray)
{
    Array a = (Array)obj;
    foreach (object arrayVal in a)
    {
        // reflect on arrayVal now
        var elementType = arrayVal.GetType();
    }
}

К сведению: я вытащил этот код из метода рекурсивного форматирования объектов (сейчас я бы использовал для него сериализацию JSON).

person JohnOpincar    schedule 02.02.2011
comment
Нет, я имею в виду GetGetMethod. Зачем вам вызывать GetSetMethod? Разве вы не пытаетесь прочитать свойство, и если это массив DeptArray, перебирать элементы и читать их? - person JohnOpincar; 02.02.2011
comment
Я пытаюсь ответить на этот вопрос. Как я могу прочитать свойства объекта, содержащего элемент типа массива, с помощью отражения в С#. Если это не вопрос, то вы должны отредактировать его. - person JohnOpincar; 02.02.2011
comment
Джон, Вы абсолютно правы в том, что мне нужно прочитать свойство и перебрать DeptArray. Когда я запускаю этот фрагмент кода. Я получаю ошибку литья в Array a = (Array)obj. В нем говорится, что ARrayClass нельзя преобразовать в массив. Как вы думаете, я пропустил что-то сказать? - person Sri Reddy; 02.02.2011