Получить значение свойства вложенных классов, если имена полей или свойств не известны во время выполнения - PullRequest
0 голосов
/ 19 января 2019

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

Предположение: каждый родительский класс имеет несколько вложенных классов. В приведенном ниже поле Родитель имеет тип. Детям проще извлекать свойства родительского уровня с простыми типами, но не свойства вложенного класса, когда имена свойств свойств вложенного класса не известны во время выполнения.

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

Желаемый: Предоставить возможность поиска родительского и всех вложенных классов без предварительного знания имен свойств вложенных классов.

public static Dictionary<string, object> DictionaryFromType(object atype)
    {
        if (atype == null) return new Dictionary<string, object>();
        var t = atype.GetType();
        var props = t.GetProperties();
        var dict = new Dictionary<string, object>();
        foreach (var prp in props)
        {
            if (prp.PropertyType.IsClass)
            {
                 // The property Names of the Nested Class are not known at 
                 // this point. This is an example.
                 // At this point I only know the property is a class. 
                 // Passing the property class name yields no result.
                    var nestedValue = GetPropertyValue(atype, "childClass.nameField");
                    if (nestedValue != null)
                    dict.Add(prp.Name, nestedValue);
            }

            var value = GetPropertyValue(atype, prp.Name);
            if (value != null)
            dict.Add(prp.Name, value);
        }
        return dict;
    }

Нижеследующее прекрасно работает, когда предоставлены соответствующий объект и вложенность. Он не пытается искать вложенный объект, в котором указано только имя объекта.

public static object GetPropertyValue(object obj, string propertyName)
    {
        var propertyNames = propertyName.Split('.');

        foreach (string t in propertyNames)
        {
            if (obj != null)
            {
                var propertyInfo = obj.GetType().GetProperty(t);
                if (propertyInfo != null)
                    obj = propertyInfo.GetValue(obj);
                else
                    obj = null;
            }
        }
        return obj;
    }

Ниже приведена модифицированная версия моего метода DictionaryFromType. Я использовал метод поиска детского свойства Хита, чтобы получить второй уровень. Это прекрасно работает на втором уровне. Все еще желательно - возможность рекурсивного поиска среди потенциальных дочерних классов, найденных в каждом из них.

public static Dictionary<string, object> DictionaryFromType(object atype)
    {
        if (atype == null) return new Dictionary<string, object>();
        var t = atype.GetType();
        var props = t.GetProperties();
        var dict = new Dictionary<string, object>();

        try
        {

        foreach (var prp in props)
        {
            if (prp.PropertyType.IsClass)
            {
                // The property Names of the Nested Class are not known at this point
                var nestedValue = GetNestedPropertyValue(atype, prp.Name);
                if (nestedValue == null) continue;
                var childType = nestedValue.GetType();
                // Loop through the first Sub Class of child properties
                // If this level is a Class, no properties will be returned.
                // Still Needed: A way to loop through Children of Children to see if the the Property is a Class
                foreach (var property in childType.GetProperties())
                {
                    var childTypePropertyValue = GetPropertyValue(atype, prp.Name + "." + property.Name);
                    if (!dict.ContainsKey(property.Name) && !dict.ContainsValue(childTypePropertyValue))
                    {
                        dict.Add(property.Name, childTypePropertyValue);
                    }
                }
            }
            else
            {
                    var value = GetPropertyValue(atype, prp.Name);
                    if (value != null)
                        if (!dict.ContainsKey(prp.Name) && !dict.ContainsValue(value))
                        {
                            dict.Add(prp.Name, value);
                        }
                }
        }
        return dict;

        }
        catch (Exception ex)
        {
            Log.Error("Error Building Dictionary : " + ex.Message);
        }

        return null;
    }

1 Ответ

0 голосов
/ 19 января 2019

Вы получили, что тип свойства был классом (который, честно говоря, почти все в .NET было бы, включая String), но сначала вам нужно отразить этот тип и перечислить его свойства, как (базовый пример; делает некоторыедопущения и ошибки обработки elides для краткости):

static object GetPropertyValue(object parent, string nestedPropertyName)
{
    object propertyValue = null;

    var tokens = nestedPropertyName.Split('.');
    foreach (var token in tokens)
    {
      var property = parent.GetType().GetProperty(token, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
      propertyValue = property.GetValue(parent);

      if (propertyValue is null) return null;
      parent = propertyValue;
    }

    return propertyValue;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...