[英]Rename Parameter in Lambda Expression C#
I have the following problem in my lambda expression: I need to rename the property because it will be passed from entity to entity.我的 lambda 表达式中存在以下问题:我需要重命名属性,因为它将从实体传递到实体。 In other words: I need to use the same expression in more than one query in different entities.
换句话说:我需要在不同实体的多个查询中使用相同的表达式。
For example:例如:
var expr = x => x.Id == converterId
To be成为
var expr = x => x.ConverterId == converterId
I have tried to do the following我尝试执行以下操作
var oldParam = expr.Parameters[0];
var newParam = Expression.Parameter(oldParam.Type, "ConverterId");
This code replaces x
not Id`此代码替换
x
而不是 Id`
This isn't trivial, but can be done my writing (subclassing) an ExpressionVisitor
, and overriding VisitMember
, making the substitution for a different Expression.Property, but using the original target expression (from the expression in the original lambda)这不是微不足道的,但可以通过我编写(子类化)一个
ExpressionVisitor
并覆盖VisitMember
完成,替换不同的 Expression.Property,但使用原始目标表达式(来自原始 lambda 中的表达式)
However, for simple cases, it is probably easier to forget that, and just build the expression-tree manually from first principles, rather than using a lambda.然而,对于简单的情况,忘记这一点可能更容易,只需根据第一原则手动构建表达式树,而不是使用 lambda。
The following shows both approaches:下面显示了这两种方法:
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.