替换表达式主体中的参数名称

发布于 2024-10-25 19:52:49 字数 827 浏览 0 评论 0原文

我正在尝试基于规范对象动态构建表达式。

我创建了一个 ExpressionHelper 类,它有一个私有表达式,如下所示:

private Expression<Func<T, bool>> expression;

public ExpressionHelper()
{
    expression = (Expression<Func<T, bool>>)(a => true);
}

然后是一些简单的方法,如下所示:

public void And(Expression<Func<T,bool>> exp);

我正在努力处理 And 方法的主体。我基本上想将主体从 exp 中剥离出来,将所有参数替换为 expression 中的参数,然后将其附加到 expression 的末尾体为 和 AndAlso。

我已经这样做了:

var newBody = Expression.And(expression.Body,exp.Body);

expression = expression.Update(newBody, expression.Parameters);

但最终我的表情看起来像这样:

{ a => e.IsActive && e.IsManaged }

有没有更简单的方法来做到这一点?或者我怎样才能撕掉那些 e 并用 a 替换它们?

I'm trying to dynamically build up expressions based on a Specification object.

I've created an ExpressionHelper class that has a private Expression like so:

private Expression<Func<T, bool>> expression;

public ExpressionHelper()
{
    expression = (Expression<Func<T, bool>>)(a => true);
}

And then some easy methods as follows:

public void And(Expression<Func<T,bool>> exp);

I'm struggling with the body of the And method. I basically want to rip the body out of exp, replace all the parameters with those in expression and then append it to the end of the expression body as and AndAlso.

I've done this:

var newBody = Expression.And(expression.Body,exp.Body);

expression = expression.Update(newBody, expression.Parameters);

But that ends up with my expression looking like this:

{ a => e.IsActive && e.IsManaged }

Is there a simpler way to do this? Or how can I rip out those e's and replace them with a's?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你列表最软的妹 2024-11-01 19:52:49

这里最简单的方法是 Expression.Invoke,例如:

public static Expression<Func<T, bool>> AndAlso<T>(
    Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(x.Body, Expression.Invoke(y, x.Parameters)),
        x.Parameters);
}

这对于 LINQ-to-Objects 和 LINQ-to-SQL 效果很好,但 EF 不支持。遗憾的是,对于 EF,您需要使用访问者来重写树。

使用以下代码: 在 c# 中组合两个 lambda 表达式

public static Expression<Func<T, bool>> AndAlso<T>(
    Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
    var newY = new ExpressionRewriter().Subst(y.Parameters[0], x.Parameters[0]).Inline().Apply(y.Body);

    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(x.Body, newY),
        x.Parameters);
}

或者在 .NET 4.0 中,使用 ExpressionVisitor

class ParameterVisitor : ExpressionVisitor
{
    private readonly ReadOnlyCollection<ParameterExpression> from, to;
    public ParameterVisitor(
        ReadOnlyCollection<ParameterExpression> from,
        ReadOnlyCollection<ParameterExpression> to)
    {
        if(from == null) throw new ArgumentNullException("from");
        if(to == null) throw new ArgumentNullException("to");
        if(from.Count != to.Count) throw new InvalidOperationException(
             "Parameter lengths must match");
        this.from = from;
        this.to = to;
    }
    protected override Expression VisitParameter(ParameterExpression node)
    {
        for (int i = 0; i < from.Count; i++)
        {
            if (node == from[i]) return to[i];
        }
        return node;
    }
}
public static Expression<Func<T, bool>> AndAlso<T>(
      Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
    var newY = new ParameterVisitor(y.Parameters, x.Parameters)
              .VisitAndConvert(y.Body, "AndAlso");
    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(x.Body, newY),
        x.Parameters);
}

The simplest approach here is Expression.Invoke, for example:

public static Expression<Func<T, bool>> AndAlso<T>(
    Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(x.Body, Expression.Invoke(y, x.Parameters)),
        x.Parameters);
}

This works fine for LINQ-to-Objects and LINQ-to-SQL, but isn't supported by EF. For EF you'll need to use a visitor to rewrite the tree, sadly.

Using the code from: Combining two lambda expressions in c#

public static Expression<Func<T, bool>> AndAlso<T>(
    Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
    var newY = new ExpressionRewriter().Subst(y.Parameters[0], x.Parameters[0]).Inline().Apply(y.Body);

    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(x.Body, newY),
        x.Parameters);
}

Or in .NET 4.0, using ExpressionVisitor:

class ParameterVisitor : ExpressionVisitor
{
    private readonly ReadOnlyCollection<ParameterExpression> from, to;
    public ParameterVisitor(
        ReadOnlyCollection<ParameterExpression> from,
        ReadOnlyCollection<ParameterExpression> to)
    {
        if(from == null) throw new ArgumentNullException("from");
        if(to == null) throw new ArgumentNullException("to");
        if(from.Count != to.Count) throw new InvalidOperationException(
             "Parameter lengths must match");
        this.from = from;
        this.to = to;
    }
    protected override Expression VisitParameter(ParameterExpression node)
    {
        for (int i = 0; i < from.Count; i++)
        {
            if (node == from[i]) return to[i];
        }
        return node;
    }
}
public static Expression<Func<T, bool>> AndAlso<T>(
      Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
    var newY = new ParameterVisitor(y.Parameters, x.Parameters)
              .VisitAndConvert(y.Body, "AndAlso");
    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(x.Body, newY),
        x.Parameters);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文