在Expression.Block中查找和删除参数声明

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

理想情况下,我应该抓取整个表达式树,并在每次在块内声明时删除参数。

知道如何用ExpressionVisitor做到这一点吗?

一个简单的类,用于从BlockExpression删除局部变量,并将其替换为您想要的任何内容。

 public class BlockVariableRemover : ExpressionVisitor { private readonly Dictionary replaces = new Dictionary(); public readonly Func Replacer; public BlockVariableRemover(Func replacer) { Replacer = replacer; } protected override Expression VisitBlock(BlockExpression node) { var removed = new List(); 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); } } 

使用它像:

 Expression> 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>(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>(block2, par1); // Test var compiled = exp2.Compile(); Console.WriteLine(compiled(10)); }