MemberExpression到MemberExpression []

时间:2010-12-17 20:48:19

标签: linq performance reflection lambda linq-expressions

目标是从两个LambdaExpressions获取一个MemberExpressions数组。第一个可转换为MethodCallExpression,它返回对象的实例(Expression<Func<T>>)。第二个Lambda表达式将获取编译的第一个表达式的结果并返回嵌套成员(Expression<Func<T,TMember>>)。我们可以假设第二个Lambda表达式只会调用嵌套属性,但可能会执行其中几个调用。

所以,我想要创建的方法的签名是:

MemberExpression[] GetMemberExpressionArray<T,TValue>(Expression<Func<T>> instanceExpression, Expression<Func<T,TValue>> nestedMemberExpression)

其中nestedMemberExpression将被假定为采用

形式的参数

parent => parent.ChildProperty.GrandChildProperty

,结果数组表示从parentChildProperty以及从ChildPropertyGrandChildProperty的值的MemberAccess。

我已使用以下扩展方法返回了最后一个MemberExpression

public static MemberExpression GetMemberExpression<T, TValue>(Expression<Func<T, TValue>> expression)
{
    if (expression == null)
    {
        return null;
    }
    if (expression.Body is MemberExpression)
    {
        return (MemberExpression)expression.Body;
    }
    if (expression.Body is UnaryExpression)
    {
        var operand = ((UnaryExpression)expression.Body).Operand;
        if (operand is MemberExpression)
        {
            return (MemberExpression)operand;
        }
        if (operand is MethodCallExpression)
        {
            return ((MethodCallExpression)operand).Object as MemberExpression;
        }
    }
    return null;
} 

现在,我知道有几种方法可以实现这一目标。对我来说最直观的是循环遍历.Expression属性以获取第一个表达式并捕获对每个MemberExpression的引用。这可能是最好的方法,但可能不是。我对使用这样的表达式所获得的性能成本并不是特别熟悉。我知道一个MemberExpression有一个MemberInfo,反射应该会影响性能。

我试图搜索表达式的信息,但我的资源在我发现的内容中非常有限。

对于如何以最佳性能和可靠性完成此任务(以及此类任务),我将不胜感激。

1 个答案:

答案 0 :(得分:1)

我不确定为什么这个被标记为 performance ,但是我能想到的从树中提取成员表达式的最简单的方式是子类{{ 3}}。这应该比手动编写逻辑“扩展”不同类型的表达式并遍历树更简单。

您可能必须覆盖ExpressionVisitor方法,以便:

  1. 捕获每个成员表达式。
  2. 拜访了孩子们。
  3. 我想这看起来像是:

    protected override Expression VisitMember(MemberExpression node)
    {
        _myListOfMemberExpressions.Add(node);
        return base.VisitMember(node);
    }
    

    我对你的剩余任务略显不清楚;看起来你想重写参数表达式,在这种情况下你可能想看看Marc Gravell的VisitMember