繁体   English   中英

重命名 Lambda 表达式中的参数 C#

[英]Rename Parameter in Lambda Expression C#

我的 lambda 表达式中存在以下问题:我需要重命名属性,因为它将从实体传递到实体。 换句话说:我需要在不同实体的多个查询中使用相同的表达式。

例如:

var expr = x => x.Id == converterId

成为

var expr = x => x.ConverterId == converterId

我尝试执行以下操作

var oldParam = expr.Parameters[0];
var newParam = Expression.Parameter(oldParam.Type, "ConverterId");

此代码替换x而不是 Id`

这不是微不足道的,但可以通过我编写(子类化)一个ExpressionVisitor并覆盖VisitMember完成,替换不同的 Expression.Property,但使用原始目标表达式(来自原始 lambda 中的表达式)

然而,对于简单的情况,忘记这一点可能更容易,只需根据第一原则手动构建表达式树,而不是使用 lambda。


下面显示了这两种方法:

using System;
using System.Linq.Expressions;

static class P
{
    static void Main()
    {
        // the compiler-generated expression-tree from the question
        Console.WriteLine(Baseline(42));

        // build our own epression trees manually
        Console.WriteLine(ByName(42, nameof(Foo.Id)));
        Console.WriteLine(ByName(42, nameof(Foo.ConverterId)));

        // take the compiler-generated expression tree, and rewrite it with a visitor
        Console.WriteLine(Convert(Baseline(42), nameof(Foo.Id), nameof(Foo.ConverterId)));
    }
    static Expression<Func<Foo, bool>> Baseline(int converterId)
    {
        // note this uses a "captured variable", so the output
        // looks uglier than you might expect
        return x => x.Id == converterId;
    }
    static Expression<Func<Foo, bool>> ByName(int converterId, string propertyOrFieldName)
    {
        var p = Expression.Parameter(typeof(Foo), "x");
        var body = Expression.Equal(
            Expression.PropertyOrField(p, propertyOrFieldName),
            Expression.Constant(converterId, typeof(int))
            );
        return Expression.Lambda<Func<Foo, bool>>(body, p);
    }

    static Expression<Func<Foo, bool>> Convert(
        Expression<Func<Foo, bool>> lambda, string from, string to)
    {
        var visitor = new ConversionVisitor(from, to);
        return (Expression<Func<Foo, bool>>)visitor.Visit(lambda);
    }
    class ConversionVisitor : ExpressionVisitor
    {
        private readonly string _from, _to;
        public ConversionVisitor(string from, string to)
        {
            _from = from;
            _to = to;
        }
        protected override Expression VisitMember(MemberExpression node)
        {
            if(node.Member.Name == _from)
            {
                return Expression.PropertyOrField(
                    node.Expression, _to);
            }
            return base.VisitMember(node);
        }

    }
}
class Foo
{
    public int Id { get; set; }

    public int ConverterId { get; set; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM