Разобрать лямбда-выражение на компоненты - PullRequest
0 голосов
/ 26 июня 2018

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

  1. В выражении должны использоваться только простые свойства или поля - без вызовов методов, запросов LINQ или чего-либо более сложного. (например, p => p.HomeAddress.City) Метод может вызвать исключение, если выражение не соответствует этим критериям.
  2. Метод должен возвращать список информации о каждом свойстве или поле: имя и тип.

Как это можно сделать?

    private List<SomeClass> ParseExpression<T1,T2>(Expression<Func<T1, T2>> func)
    {
        // ??
    }

1 Ответ

0 голосов
/ 27 июня 2018

Это:

private static IReadOnlyList<Tuple<string, Type>> ParseExpression<T1, T2>(Expression<Func<T1, T2>> func)
{
    var par = func.Parameters[0];

    var lst = new List<Tuple<string, Type>>();

    Expression exp = func.Body;

    while (exp != par)
    {
        if (exp.NodeType != ExpressionType.MemberAccess)
        {
            throw new Exception(exp.ToString());
        }

        MemberExpression me = (MemberExpression)exp;

        MemberInfo mi = me.Member;

        if (mi.MemberType == MemberTypes.Field)
        {
            FieldInfo fi = (FieldInfo)mi;
            lst.Add(Tuple.Create(fi.Name, fi.FieldType));
        }
        else if (mi.MemberType == MemberTypes.Property)
        {
            PropertyInfo pi = (PropertyInfo)mi;
            lst.Add(Tuple.Create(pi.Name, pi.PropertyType));
        }
        else
        {
            throw new Exception(exp.ToString());
        }

        exp = me.Expression;
    }

    lst.Reverse();

    return lst;
}

Пример:

class Cl1
{
    public Cl2 Cl2; 
}

class Cl2
{
    public string Str { get; set; }
}

и затем:

var result = ParseExpression<Cl1, string>(x => x.Cl2.Str);

foreach (var el in result)
{
    Console.WriteLine($"{el.Item1}: {el.Item2}");
}
...