Как получить значение из вложенного списка с отражением? - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть вложенный список с именем filterTarget.

Пример содержимого:

filterTarget = { Id: 1
InventoryDescription: {Type: "Machine", Code: "1/1", Description: "1", Category: "1", StockCode: "1", …}
InventoryRecordDetails: []
Length: "1"
Life: "04.02.2019"
Location: null
Model: "1" }

Пример, в котором я хочу получить значение Code of InventoryDescription.

Я написал этот код для двух слоев, но он выглядит грязным инедостаточно.И это не общее.

filterTarget = filterTarget
          .Where(x =>  x.GetType()  
                        .GetProperty(fieldval1)
                        .PropertyType
                        .GetProperty(fieldval2)
                        .GetValue(x.GetType()
                                   .GetProperty(fieldval1)
                                   .GetValue(x))
                        .ToString()?
                        .ToLower() == deger)
          .ToList();

Как получить значение из вложенного списка с отражением и linq?

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

filterTarget - мой вложенный список.

поле - упорядоченная строка свойства.

  filterTarget = (from f in filterTarget
  let temp = GetPropertyValue(f, Field)
  where temp?.ToString().ToLower() == "deger"
  select f).ToList();

  private static object GetPropertyValue<T>(T filterTarget, string field)
  {
   string[] fields = field.Split('.');
   object value = filterTarget;
   fields?.ToList().ForEach(p =>
   {
      value = value.GetType().GetProperty(p).GetValue(value);
   });

    return value;
  }
0 голосов
/ 06 февраля 2019

Если вы ищете решение linq, тогда let будет вашим другом:

filterTarget = (from f in filterTarget
                let temp = f.GetType().GetProperty(fieldval1).GetValue(f)
                let temp2 = temp.GetType().GetProperty(fieldval2).GetValue(temp)
                where temp2.ToString().ToLower() == deger
                select f).ToList();

Но лично я нахожу его нечитаемым.Нормальный цикл с подходящим условием if был бы гораздо более понятен:

public IEnumerable<T> FilterMyList<T>(IEnumerable<T> list, string fieldval1, string fieldval2, string deger)
{
    foreach (var element in list)
    {
        var nesteValue1 = element.GetType().GetProperty(fieldval1).GetValue(element);
        var nestedValue2 = nesteValue1.GetType().GetProperty(fieldval2).GetValue(nesteValue1);
        if (nestedValue2.ToString().ToLower() == deger)
        {
            yield return element;
        }
    }
}

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

public IEnumerable<T> FilterMyListRecursive<T>(IEnumerable<T> list, string searchpattern, params string [] propertynames) where T: class
{
    foreach (var element in list)
    {       
        if (TryNestedRecursiveDescend(element, searchpattern, propertynames))
        {
            yield return element;
        }       
    }
}

private bool TryNestedRecursiveDescend<T>(T obj, string searchpattern, params string [] propertynames) where T: class
{   
    var nestedValue = obj.GetType().GetProperty(propertynames.First()).GetValue(obj);
    // if you are at the lowest level that you can check
    if (fieldvalues.Length == 1)
    {       
        return nestedValue.ToString().ToLower() == searchpattern;
    }
    else
    {
        // recursive call with the remaining propertynames
        return TryNestedDescend(nestedValue, searchpattern, propertynames.Skip(1).ToArray());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...