2

我正在尝试Utility.GetString(MyEntity.SomePropertyWithRelatedEntity)=="abc"用表达式访问者替换(简化)之类的函数调用,例如p => p.SubRelatedEntities.FirstOrDefault(sre => sre.SomeFlag==true).SomePropertyWithRelatedEntity.

这意味着,数据模型如下: MyEntity -> RelatedEntity -> SubRelatedEntity

我正在尝试SubRelatedEntity根据 中的一些规则从 中返回一个字符串值RelatedEntity,因此我不必在每次使用中重新编写/复制/粘贴整个过滤规则;这就是为什么我放入一个“调用签名”,所以我的表达式访问者可以识别它并将假调用替换Utility.GetString为一些复杂的 lambda 表达式。

我的表达式访问者包含以下内容:

    public override Expression Visit(Expression node)
    {
        if (node == null)
            return null;

        Expression result = null;

        if (node.NodeType == ExpressionType.Call)
        {
            MethodCallExpression mce = node as MethodCallExpression;
            if (mce.Method.DeclaringType == typeof(Utility) && mce.Method.Name == "GetString")
            {
                Expression<Func<RelatedEntity, string>> exp = re => re.SubRelatedEntities.FirstOrDefault(sre => sre.SomeFlag == true).SomeStringValue;
                result = exp.Body;

            }
            else
                result = base.Visit(node);
        }
        else
            result = base.Visit(node);

        return result;

    }

现在,问题是,当调用注入的 lambda 表达式时,“sre”参数没有绑定。经过大量研究,我看到 lambda 参数应该替换为另一个表达式访问者,特别是搜索新参数并用旧参数替换它们。然而,在我的情况下,我没有“旧参数”——我有一个表达式MyEntity.SomePropertyWithRelatedEntity(例如,一个填充了相关实体的属性),我需要以某种方式将其插入到生成的 lambda 中。

我希望我的问题是可以理解的。感谢您的任何见解!

4

1 回答 1

3

在长时间没有答案并努力寻找解决方案之后,我最终解决了它:o)!它是这样的:

新注入的 lambda 表达式得到一个 ParameterExpression - 嗯,这是一个“助手”,在直接调用 lambda 时使用,这是我不想要的(因此,调用 ToEnumerable 时出现“参数未绑定”异常)。所以,线索是制作一个专门的 ExpressionVisitor,用原始表达式替换这个帮助器,这当然在方法调用的 Arguments[] 中可用,我试图替换它。

像魅力一样工作,像这样您可以重用相同的 LINQ 表达式,例如可重用的子查询,而不是一直编写所有相同的 LINQ 内容。还要注意,在 EF 中不允许调用方法的表达式,在 Linq2Sql 中它可以工作。此外,所有提议的网络文章仅替换参数实例,当构造/合并更多 LINQ 表达式时 - 在这里,我需要用伪造的方法调用参数替换参数,例如不应该调用该方法,它只代表对于代码标记,我需要在其中放置 LINQ 子查询。

希望这对某人有所帮助,最后它非常简单和合乎逻辑,当人们知道如何构造表达式树时;-)。

再见,安德烈

于 2012-05-26T13:14:52.420 回答