将Lambda表达式解析为组件

时间:2018-06-26 20:46:56

标签: c# reflection lambda expression

我正在编写一种方法,该方法接受一个lambda表达式作为参数并从左到右解析其属性。应该满足以下条件:

  1. 表达式只能使用简单的属性或字段-不能使用任何方法调用或LINQ查询或任何更复杂的函数。 (例如p => p.HomeAddress.City)如果表达式不满足这些条件,则该方法可能会引发异常。
  2. 该方法应返回有关每个属性或字段的信息列表:名称和类型。

这怎么实现?

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

1 个答案:

答案 0 :(得分:1)

此:

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}");
}