您的位置:知识库 »

打造自己的LINQ Provider(上):Expression Tree揭秘

作者: TerryLee  来源: 博客园  发布时间: 2008-09-19 23:10  阅读: 58537 次  推荐: 4   原文链接   [收藏]  
摘要:在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHibernate、LINQ to Google等,大有“一切皆LINQ”的趋势。LINQ本身也提供了很好的扩展性,使得我们可以轻松的编写属于自己的LINQ Provider。
[1] 认识表达式目录树1
[2] 认识表达式目录树2
[3] 表达式目录树与委托
[4] 执行表达式目录树
[5] 访问与修改表达式目录树
[6] 为什么需要表达式目录树和总结

访问与修改表达式目录树

在本文一开始我就说过, 通过解析表达式目录树,我们可以实现一些特定功能,既然要解析表达式目录树,对于表达式目录树的访问自然是不可避免的。在.NET Framework中,提供了一个抽象的表达式目录树访问类ExpressionVisitor,但它是一个internal的,我们不能直接访问。幸运的是,在MSDN中微软给出了ExpressionVisitor类的实现,我们可以直接拿来使用。该类是一个抽象类,微软旨在让我们在集成ExpressionVisitor的基础上,实现自己的表达式目录树访问类。现在我们来看简单的表达式目录树:

static void Main(string[] args)
{
    Expression<Func<int, int, int>> lambda = (a, b) => a + b * 2;
 
    Console.WriteLine(lambda.ToString());
} 

输出后为:

TerryLee_0164

现在我们想要修改表达式目录树,让它表示的Lambda表达式为(a,b)=>(a - (b * 2)),这时就需要编写自己的表达式目录树访问器,如下代码所示:

public class OperationsVisitor : ExpressionVisitor
{
    public Expression Modify(Expression expression)
    {
        return Visit(expression);
    }
 
    protected override Expression VisitBinary(BinaryExpression b)
    {
        if (b.NodeType == ExpressionType.Add)
        {
            Expression left = this.Visit(b.Left);
            Expression right = this.Visit(b.Right);
            return Expression.Subtract(left,right);
        }
 
        return base.VisitBinary(b);
    }
}

使用表达式目录树访问器来修改表达式目录树,如下代码所示:

static void Main(string[] args)
{
    Expression<Func<int, int, int>> lambda = (a, b) => a + b * 2;
 
    var operationsVisitor = new OperationsVisitor();
    Expression modifyExpression = operationsVisitor.Modify(lambda);
 
    Console.WriteLine(modifyExpression.ToString());
}

运行后可以看到输出:

TerryLee_0165

似乎我们是修改表达式目录树,其实也不全对,我们只是修改表达式目录树的一个副本而已,因为表达式目录树是不可变的,我们不能直接修改表达式目录树,看看上面的OperationsVisitor类的实现大家就知道了,在修改过程中复制了表达式目录树的节点。

4
0

热门文章

    最新文章

      最新新闻

        热门新闻