C# Преобразование рекурсивной итерации значений свойств для свойства List <> - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть следующий метод, который я использую, чтобы перебрать все свойства (только свойства) в моих классах и напечатать на экране их имена и значения, которые они содержат, если они есть.

        public static void PrintProperties(object obj, int indent = 1)
        {
        if ( obj == null )
            return;
        string indentString = new string (' ', indent);

        Type objType = obj.GetType ();
        PropertyInfo[] properties = objType.GetProperties ();

        foreach ( PropertyInfo property in properties )
        {
            object propValue = property.GetValue (obj, null);
            var elems = propValue as IList;
            if ( elems != null )
            {
                foreach ( var item in elems )
                {
                    PrintProperties (item, indent + 3);
                }
            }
            else
            {
                if ( property.PropertyType.Assembly == objType.Assembly )
                {
                    Console.WriteLine("{0}{1}:", indentString, property.Name);

                    PrintProperties (propValue, indent + 2);
                }
                else
                {
                    Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
                }
            }
            }

К сожалению, я изменяю свойство в одном из моих классов от строки до List<string> для размещения нескольких значений, которые мне нужно было назначить там, и теперь я получаю ошибку System.Reflection.TargetParameterCountException: 'Parameter count mismatch.', которую не знаю, как исправить, и, скорее всего, потому, что у меня есть свойство, которое является списком. Как я могу исправить, чтобы, когда я сталкиваюсь с таким свойством, перечислить все его значения? Может ли кто-нибудь помочь мне, пожалуйста?

Ответы [ 2 ]

1 голос
/ 25 февраля 2020

Проблема в этой строке, где возникает ошибка:

object propValue = property.GetValue (obj, null);

Не имеет ничего общего со списком как таковым. Это рекурсивная природа вашего метода, пытающегося перечислить все свойства string. Простое решение, если вы хотите только напечатать значения списка, состоит в том, чтобы изменить часть, перечисляющую список, следующим образом:

var elems = propValue as IList;
if ( elems != null )
{
     Console.WriteLine("{0}{1}:", indentString, property.Name);
     foreach ( var item in elems )
     {
            Console.WriteLine("{0}{1}",new string (' ', indent+2),item);
     }
}

https://dotnetfiddle.net/NBOA4u

1 голос
/ 25 февраля 2020

Вам нужно сделать три вещи, чтобы исправить вашу реализацию:

  1. Специально обрабатывать строки (потому что иначе они будут рассматриваться как массивы символов в вашей реализации).
  2. Специально обрабатывать массивы (иначе вы получите исключение, которое вы видите).
  3. Распечатайте значение каждого элемента, а не только его свойства. В противном случае, если этот элемент, скажем, int, он не будет распечатан.

Что-то вроде этого должно работать:

public static void PrintProperties(object obj, int indent = 1)
{
    if (obj == null)
        return;

    string indentString = new string(' ', indent);

    Type objType    = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();

    foreach (PropertyInfo property in properties)
    {
        object propValue;

        if (objType == typeof(string))
            return; // Handled at a higher level, so nothing to do here.

        if (property.PropertyType.IsArray)
            propValue = (Array)property.GetValue(obj);
        else
            propValue = property.GetValue(obj, null);

        var elems = propValue as IList;

        if (elems != null)
        {
            Console.WriteLine("{0}{1}: IList of {2}", indentString, property.Name, propValue.GetType().Name);

            for (int i = 0; i < elems.Count; ++i)
            {
                Console.WriteLine("{0}{1}[{2}] == {3}", indentString, property.Name, i, elems[i]);

                if (objType != typeof(string))
                    PrintProperties(elems[i], indent + 3);
            }
        }
        else
        {
            if (property.PropertyType.Assembly == objType.Assembly)
            {
                Console.WriteLine("{0}{1}:", indentString, property.Name);

                PrintProperties(propValue, indent + 2);
            }
            else
            {
                Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
            }
        }
    }
}

Возможно, вы будете Я хочу настроить вывод в соответствии с тем, что вы на самом деле хотите, но это должно дать вам суть.

...