我想使用表达式树将() => a - 1 + b + 1
lambda转换为类似() => a-- + b++
的东西。
我实现了从ExpressionTreeTransformer.cs
继承并覆盖ExpressionVisitor.cs
方法的类VisitBinary
:
protected override Expression VisitBinary(BinaryExpression node)
{
if (!TryGetNumberValueFromExpressionNode(node.Left, out var leftNodeValue))
{
return base.VisitBinary(node);
}
if (!TryGetNumberValueFromExpressionNode(node.Right, out var rightNodeValue) || rightNodeValue != 1)
{
return base.VisitBinary(node);
}
var resultedExpression = node.NodeType switch
{
ExpressionType.Add => Expression.Increment(Expression.Constant(leftNodeValue)),
ExpressionType.Subtract => Expression.Decrement(Expression.Constant(leftNodeValue)),
_ => base.VisitBinary(node)
};
return resultedExpression;
}
如果加上() => (a - 1) + (b + 1)
这样的括号,效果很好,但是如果我们尝试()=> a - 1 + b + 1
经过一番调查,我发现原因是表达式树如何构建节点。 没有括号的步骤如下:
表达式节点在处理程序链中处理:
_expressionHandlers = new MemberExpressionHandler();
_expressionHandlers.SetSuccessor(new ConstantExpressionHandler());
变量处理程序:
public class MemberExpressionHandler : AbstractTreeExpressionHandler
{
public override bool Handle(Expression expressionNode, out int nodeValue)
{
if (expressionNode is MemberExpression memberExpression)
{
var constantExpression = memberExpression.Expression as ConstantExpression;
var field = (FieldInfo)memberExpression.Member;
if (constantExpression != null)
{
var value = field.GetValue(constantExpression.Value);
var isNumber = int.TryParse(value.ToString(), out nodeValue);
if (isNumber)
{
return true;
}
}
}
else
{
if (_successor != null)
{
return _successor.Handle(expressionNode, out nodeValue);
}
}
nodeValue = 0;
return false;
}
}
常量处理程序:
public class ConstantExpressionHandler : AbstractTreeExpressionHandler
{
public override bool Handle(Expression expressionNode, out int nodeValue)
{
var isConstant = expressionNode is ConstantExpression;
var isNumber = int.TryParse(((ConstantExpression)expressionNode).Value.ToString(), out nodeValue);
if (isConstant && isNumber)
{
return true;
}
return false;
}
}
问:我很困,请分享您的经验如何以正确的方式解决此任务
P.s结果:
(Decrement(0) + Increment(1))
() => ((Decrement(0) +
value(ExpressionTreeModule.Program+<>c__DisplayClass0_0).b) + 1)
答案 0 :(得分:1)
我认为当您发现1
的恒定加减时,您需要检查左侧,并确定是否可以将加减乘以增量/减量。这是我的示例代码:
public class UnaryConstant1 : ExpressionVisitor {
protected override Expression VisitBinary(BinaryExpression node) {
if (node.Right is ConstantExpression c && c.Type.IsNumeric() && (Int32)c.Value == 1) {
if (node.NodeType == ExpressionType.Add || node.NodeType == ExpressionType.Subtract) {
if (node.Left is MemberExpression) {
if (node.NodeType == ExpressionType.Add)
return Expression.Increment(node.Left);
else
return Expression.Decrement(node.Left);
}
else if (node.Left is BinaryExpression left && (left.NodeType == ExpressionType.Add || left.NodeType == ExpressionType.Subtract)) {
Expression right;
if (node.NodeType == ExpressionType.Add)
right = Expression.Increment(left.Right);
else
right = Expression.Decrement(left.Right);
if (left.NodeType == ExpressionType.Add)
return Expression.Add(Visit(left.Left), right);
else
return Expression.Subtract(Visit(left.Left), right);
}
}
}
return base.VisitBinary(node);
}
}