[英]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.