C# 将Lambda表达式转换/克隆为另一个具有不同参数的表达式

C# 将Lambda表达式转换/克隆为另一个具有不同参数的表达式,c#,linq,C#,Linq,我不知道是否有一个简单的方法来实现我的目标。 一方面,我有一个以编程方式构建的表达式,另一方面,我有一个手动输入的相同表达式。假设它们完全相同,我需要更改为手册中的ParameterExpression,使其与另一个相等。 下面是一个示例代码 //I have this expression (for example) Expression<Func<Bar,bool>> old_expr = x => x.Name == x.ColBar; //I want to

我不知道是否有一个简单的方法来实现我的目标。 一方面,我有一个以编程方式构建的表达式,另一方面,我有一个手动输入的相同表达式。假设它们完全相同,我需要更改为手册中的ParameterExpression,使其与另一个相等。 下面是一个示例代码

//I have this expression (for example)
Expression<Func<Bar,bool>> old_expr = x => x.Name == x.ColBar;
//I want to change parameter from x to y
//I already have the y parameter in the code, let's say it is the following
ParameterExpression py = Expression.Parameter(typeof(Bar), "y");
//this is what I have tried, but it is *not* complete neither generic
Expression expr_to_do;
if (old_expr.Body.NodeType.Equals(ExpressionType.Convert)) {
    UnaryExpression convEx = old_expr.Body as UnaryExpression;
    expr_to_do = convEx.Operand;
} else {
    expr_to_do  = old_expr.Body;
}
//TODO: convert the BinarayExpression eqEx, etc... etc...
var newLambda = Expression.Lambda(expr_to_do, new ParameterExpression[1]{py});

//Again, what I want to get is the following, where y *is* the parameter defined *above* 
Expression<Func<Bar,bool>> new_expr = y => y.Name == y.ColBar;
//The code/method I'm looking for - if it does exist a method to do that - must be generic enough not specific to this single expression

我是否遗漏了一些简化流程的内容?

如果我没弄错,您需要做的与这里的答案完全相同的事情

编辑

在这种情况下,有两个不同的表达式,替换是从一个参数到另一个表达式。这里只有一个起始表达式,而且替换是从一个参数到另一个参数。 下面的代码似乎工作正常

var map = old_expr.Parameters.ToDictionary(p => p, p => py);
var reboundBody = ParameterRebinder.ReplaceParameters(map, old_expr.Body);
var lambda = Expression.Lambda<Func<Bar,bool>>(reboundBody, py);
var map=old_expr.Parameters.ToDictionary(p=>p,p=>py);
var Body=参数Rebinder.ReplaceParameters(映射,旧的表达式体);
var lambda=表达式.lambda(体,py);
客人呢

public class ParameterRebinder : ExpressionVisitor
{
    private readonly Dictionary<ParameterExpression, ParameterExpression> Map;

    public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
    {
        this.Map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
    }

    public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
    {
        return new ParameterRebinder(map).Visit(exp);
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        ParameterExpression replacement;
        if (this.Map.TryGetValue(node, out replacement))
        {
            return replacement;
            //return this.Visit(replacement);
        }
        return base.VisitParameter(node);
    }
}
公共类参数reBinder:ExpressionVisitor
{
私有只读字典映射;
公共参数索引(字典映射)
{
this.Map=Map??新字典();
}
公共静态表达式替换参数(字典映射、表达式表达式)
{
返回新参数浏览器(map)。访问(exp);
}
受保护的重写表达式VisitParameter(ParameterExpression节点)
{
参数表达替换;
if(this.Map.TryGetValue(节点,out替换))
{
退换货;
//回访(更换);
}
返回基本访问参数(节点);
}
}

我编辑了您的答案,以解释我的案例中的不同情况,并包含了修改后的代码。我不确定您是否真的要用参数替换参数,因此无法向您展示具体的解决方案,很高兴链接帮助了您。
public class ParameterRebinder : ExpressionVisitor
{
    private readonly Dictionary<ParameterExpression, ParameterExpression> Map;

    public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
    {
        this.Map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
    }

    public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
    {
        return new ParameterRebinder(map).Visit(exp);
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        ParameterExpression replacement;
        if (this.Map.TryGetValue(node, out replacement))
        {
            return replacement;
            //return this.Visit(replacement);
        }
        return base.VisitParameter(node);
    }
}