C# 在Expression.Block中查找并删除参数声明

C# 在Expression.Block中查找并删除参数声明,c#,expression,expressionvisitor,C#,Expression,Expressionvisitor,我知道如何用ExpressionVisitor替换参数,但我想知道是否有办法从Expression.Block中删除参数 理想情况下,我应该对整个表达式树进行爬网,并在每次在块内声明参数时删除该参数 您知道如何使用ExpressionVisitor实现这一点吗?一个简单的类,用于从块表达式中删除局部变量,并用所需的任何内容替换它们 public class BlockVariableRemover : ExpressionVisitor { private readonly Dictio

我知道如何用ExpressionVisitor替换参数,但我想知道是否有办法从Expression.Block中删除参数

理想情况下,我应该对整个表达式树进行爬网,并在每次在块内声明参数时删除该参数


您知道如何使用ExpressionVisitor实现这一点吗?

一个简单的类,用于从
块表达式中删除局部变量,并用所需的任何内容替换它们

public class BlockVariableRemover : ExpressionVisitor
{
    private readonly Dictionary<Expression, Expression> replaces = new Dictionary<Expression, Expression>();

    public readonly Func<ParameterExpression, int, Expression> Replacer;

    public BlockVariableRemover(Func<ParameterExpression, int, Expression> replacer)
    {
        Replacer = replacer;
    }

    protected override Expression VisitBlock(BlockExpression node)
    {
        var removed = new List<Expression>();

        var variables = node.Variables.ToList();

        for (int i = 0; i < variables.Count; i++)
        {
            var variable = variables[i];
            var to = Replacer(variable, i);

            if (to != variable)
            {
                removed.Add(variable);
                replaces.Add(variable, to);
                variables.RemoveAt(i);
                i--;
            }
        }

        if (removed.Count == 0)
        {
            return base.VisitBlock(node);
        }

        var expressions = node.Expressions.ToArray();

        for (int i = 0; i < expressions.Length; i++)
        {
            expressions[i] = Visit(expressions[i]);
        }

        foreach (var rem in removed)
        {
            replaces.Remove(rem);
        }

        return Expression.Block(variables, expressions);
    }

    public override Expression Visit(Expression node)
    {
        Expression to;

        if (node != null && replaces.TryGetValue(node, out to))
        {
            return base.Visit(to);
        }

        return base.Visit(node);
    }
}
公共类BlockVariableRemover:ExpressionVisitor
{
专用只读字典替换=新字典();
公共只读Func替换程序;
公共块变量删除程序(Func替换程序)
{
替换者=替换者;
}
受保护的重写表达式VisitBlock(块表达式节点)
{
var removed=新列表();
var variables=node.variables.ToList();
对于(int i=0;i
像这样使用它:

Expression<Func<int, int>> exp;

{
    var var1 = Expression.Variable(typeof(int), "var1");
    var var2 = Expression.Variable(typeof(long), "var2");

    var par1 = Expression.Parameter(typeof(int), "par1");

    var block = Expression.Block(new[] { var1, var2 }, Expression.Increment(var1));

    exp = Expression.Lambda<Func<int, int>>(block, par1);

    // Test
    var compiled = exp.Compile();
    Console.WriteLine(compiled(10));
}

// Begin replace
{
    var par1 = exp.Parameters[0];

    var block2 = new BlockVariableRemover(
        // ix is the index of the variable, 
        // return x if you don't want to modify,
        // return whatever you want (even Expression.Empty()) to do 
        // a replace
        (x, ix) => ix == 0 && x.Type == typeof(int) ? par1 : x)
        .Visit(exp.Body);

    // Final result
    var exp2 = Expression.Lambda<Func<int, int>>(block2, par1);

    // Test
    var compiled = exp2.Compile();
    Console.WriteLine(compiled(10));
}
表达式exp;
{
var var1=表达式变量(typeof(int),“var1”);
var var2=表达式变量(typeof(long),“var2”);
var par1=表达式参数(typeof(int),“par1”);
var block=Expression.block(new[]{var1,var2},Expression.Increment(var1));
exp=表达式λ(块,par1);
//试验
var compiled=exp.Compile();
Console.WriteLine(编译(10));
}
//开始替换
{
var par1=exp.Parameters[0];
var block2=新的BlockVariableRemover(
//ix是变量的索引,
//如果不想修改,则返回x,
//返回您想要执行的任何操作(即使是Expression.Empty())
//替代品
(x,ix)=>ix==0&&x.Type==typeof(int)?par1:x)
.访问(exp.Body);
//最终结果
var exp2=Expression.Lambda(block2,par1);
//试验
var compiled=exp2.Compile();
Console.WriteLine(编译(10));
}

您能举例说明您想要获得什么吗?如果您有
(x,y)=>x+y+1
,删除y意味着什么?您想要
x=>x+1
?但是如果你有
(x,y)=>Math.Max(x,y)
,会发生什么呢?或者更复杂的表达式。。。您不能删除一个参数并留下一个洞。这是一种情况。我的表达式生成器声明了一个列表。此表达式生成器递归使用,因此声明了许多列表(通过这种方式将各种项目插入其“本地”列表)。通过删除中列表的内部声明并用ExpressionVisitor替换参数,我可以重定向唯一列表(第一次调用我的expression builder时声明的列表)中的所有插入。因此,用表示“主”列表的参数替换
新列表(
an ExpressionType.new
)。因此,您将得到如下内容:
var localList=masterList;localList.Add(something)
这个问题太具体了,没有具体的例子是无法解决的。除了我的具体案例。问题是如何删除而不是替换参数。这个问题在这方面并不具体。param是指块的局部变量吗?(所以
Expression.Block(variable1,variable2,expression1,expression2)
您想删除
variable1
(和/或
variable2
)?我会尝试一下,几天后告诉您。谢谢。