【问题标题】:Parse a lambda expression into components将 lambda 表达式解析为组件
【发布时间】:2018-06-26 20:46:56
【问题描述】:

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

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

如何做到这一点?

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

【问题讨论】:

  • 获取 LINQPad 的副本,您可以Dump 不同表达式的表达式值,看看您需要做什么来解析它们。

标签: c# reflection lambda expression


【解决方案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}");
}

【讨论】:

  • 这种方法看起来很有希望。在接受这个答案之前,我会稍后再看。谢谢。
猜你喜欢
  • 2010-09-19
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多