是否有现有的库/技术来减少.NET表达式树?

时间:2012-08-06 00:37:14

标签: .net optimization lambda expression-trees

我正在翻译表达式树,我想知道是否有适用于减少/优化树中操作的现有库或技术。

例如,我希望能够按如下方式折叠一系列连续的否定操作:

arg => !!!!!!!(getValue(arg))
reduces to arg => !getValue(arg)

...或者将一个否定后面的相等操作转换为非等于操作:

arg => !(getValue(arg) == 3)
reduces to arg => getValue(arg) != 3

......或者将De Morgan的法律适用于一般的逻辑表达式:

arg => !(getValue(arg) < 3 || getValue(arg) >= 5))
reduces to arg => getValue(arg) >= 3 && getValue(arg) < 5

[为了简洁起见,我在上面的缩小格式中使用了lambda表达式。]

我知道这些工具不能应用于表达式树的所有可能评估,但它们似乎对严格使用逻辑运算的表达式树类有用。

是否存在构建执行这些任务的表达式树计算器的现有参考?

1 个答案:

答案 0 :(得分:1)

看起来没有可重用的.NET Framework组件来解决问题中提出的要求。但是,Andrey Shchekin's tool reference为如何编写所需组件提供了很好的参考。

这是一个片段,它解决了顺序Not()运算符的取消,Not()运算符在二进制表达式中的分布以及De Morgan定律的应用。

public class NotCollapser : ExpressionVisitor
{
    // Incomplete list; others removed for brevity.
    private static readonly IDictionary<ExpressionType, Func<BinaryExpression, BinaryExpression>> NotDistributionMap = 
    {
        { ExpressionType.Equal, e => Expression.MakeBinary(ExpressionType.NotEqual, e.Left, e.Right) },
        { ExpressionType.NotEqual, e => Expression.MakeBinary(ExpressionType.Equal, e.Left, e.Right) },
        { ExpressionType.GreaterThan, e => Expression.MakeBinary(ExpressionType.LessThanOrEqual, e.Left, e.Right) },
        { ExpressionType.AndAlso, e => Expression.MakeBinary(ExpressionType.OrElse, Expression.Not(e.Left), Expression.Not(e.Right)) },
        { ExpressionType.OrElse, e => Expression.MakeBinary(ExpressionType.AndAlso, Expression.Not(e.Left), Expression.Not(e.Right)) }
    };


    protected override Expression VisitUnary(UnaryExpression expression)
    {
        if (expression.NodeType == ExpressionType.Not)
        {
            if (expression.Operand.NodeType == ExpressionType.Not)
            {
                return Visit((expression.Operand as UnaryExpression).Operand);
            }

            if (NotDistributionMap.ContainsKey(expression.Operand.NodeType))
            {
                var distribute = NotDistributionMap[expression.Operand.NodeType];
                return Visit(distribute(expression.Operand as BinaryExpression));
            }
        }

        return base.VisitUnary(expression);
    }
}