`
terryfeng
  • 浏览: 504464 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

LINQ 表达式树 Expression

阅读更多

在 LINQ to Objects 中,扩展方法需要将一个委托类型作为参数,这样就可以将λ表达式赋予参数。

λ达式也可以赋予Expression<T>类型的参数。Expression<T>类型指定,来自于λ表达式的表达式树存储在程序集中。

这样,就可以在运行期间分析表达式,并进行优化,以便于查询数据源。

下面看看一个前面使用的查询表达式:

var brazilRacers = from r in racers
where r.Country == "Brazil"
orderby r.Wins
select r;

这个查询表达式使用了扩展方法Where、OrderBy 和Select。

Enumerable 类定义了Where 扩展方法,并将委托类型Func<T,bool>作为参数谓词。

public static IEnumerable<T> Where<T> (this IEnumerable<T> source, Func<T,bool> predicate);

这样,就把λ表达式赋予谓词。这里λ 表达式类似于前面介绍的匿名方法。

Func<T, bool> predicate = r.Country == "Brazil";

Enumerable 类不是唯一定义了扩展方法Where 的类。

Queryable<T>类也定义了Where扩展方法。

这个类对Where 扩展方法的定义是不同的:
public static IQueryable<T> Where<T> (this IQueryable<T> source,
Expression<Func<T,bool>> predicate);

其中,λ 表达式赋予类型Expression<T>,它的操作是不同的:

Expression<Func<T, bool>> predicate = r.Country == "Brazil";

除了使用委托之外,编译器还会把表达式树放在程序集中。表达式树可以在运行期间读取。
表达式树从派生自抽象基类Expression 的类中建立。

Expression 类与Expression<T>不同。

继承了Expression 的表达式类有BinaryExpression、ConstantExpression、InvocationExpression、LambdaExpression 、
NewExpression 、NewArrayExpression 、TernaryExpression 、UnaryExpression 等。编译器会从λ 表达式中创建表达式树。

例如,λ表达式r.Country==“Brazil”使用了ParameterExpression、MemberExpression、ConstantExpression
和MethodCallExpression,来创建一个表达式树,将该树存储在程序集中。之后在运行期间使用这个树,创建一个用于底层数据源的优化查询。

方法 DisplayTree()在控制台上图形化地显示表达式树。其中传送了一个Expression 对象,并根据表达式
类型,把表达式的一些信息写到控制台上。根据表达式的类型,递归调用方法DisplayTree()。
提示:在这个方法中,没有处理所有的表达式类型,只处理了下列示例表达式中使用的类型:

 

private static void DisplayTree(int indent, string message, Expression expression)
{
    string output = String.Format("{0} {1}! NodeType: {2}; Expr: {3} ", "".PadLeft(indent, '>'), message, expression.NodeType, expression);

    indent++;
    switch (expression.NodeType)
    {
        case ExpressionType.Lambda:
            Console.WriteLine(output);
            LambdaExpression lambdaExpr = (LambdaExpression)expression;
            foreach (var parameter in lambdaExpr.Parameters)
            {
                DisplayTree(indent, "Parameter", parameter);
            }
            DisplayTree(indent, "Body", lambdaExpr.Body);
            break;
        case ExpressionType.Constant:
            ConstantExpression constExpr = (ConstantExpression)expression;
            Console.WriteLine("{0} Const Value: {1}", output, constExpr.Value);
            break;
        case ExpressionType.Parameter:
            ParameterExpression paramExpr = (ParameterExpression)expression;
            Console.WriteLine("{0} Param Type: {1}", output, paramExpr.Type.Name);
            break;
        case ExpressionType.Equal:
        case ExpressionType.AndAlso:
        case ExpressionType.GreaterThan:
            BinaryExpression binExpr = (BinaryExpression)expression;
            if (binExpr.Method != null)
                Console.WriteLine("{0} Method: {1}", output, binExpr.Method.Name);
            else
                Console.WriteLine(output);
            DisplayTree(indent, "Left", binExpr.Left);
            DisplayTree(indent, "Right", binExpr.Right);
            break;
        case ExpressionType.MemberAccess:
            MemberExpression memberExpr = (MemberExpression)expression;
            Console.WriteLine("{0} Member Name: {1}, Type: {2}", output, memberExpr.Member.Name, memberExpr.Type.Name);
            DisplayTree(indent, "Member Expr", memberExpr.Expression);
            break;
        default:
            Console.WriteLine();
            Console.WriteLine("....{0} {1}", expression.NodeType, expression.Type.Name);
            break;
    }
}

 

前面已经介绍了用于显示表达式树的表达式。

这是一个λ表达式,它使用一个Racer 参数,表达式体提取赢得比赛次数超过6 次的巴西赛手:

private static void Expressions()
        {
            Expression<Func<Racer, bool>> expression = r => r.Country == "Brazil" && r.Wins > 6;

            DisplayTree(0, "Lambda", expression);
        }

 

下面看看结果。λ表达式包含一个Parameter 和一个AndAlso 节点类型。

AndAlso 节点类型的左边是一个Equal 节点类型,

右边是一个GreaterThan 节点类型。

Equal 节点类型的左边是MemberAccess 节点类型,

右边是Constant 节点类型。

image

使用类型Expression<T>的一个例子是LINQ to SQL。

LINQ to SQL 用Expression<T>参数定义了扩展方法。
这样,访问数据库的LINQ 提供程序就可以读取表达式,创建一个运行期间优化的查询,从数据库中获取数
据。

分享到:
评论

相关推荐

    LINQ与DLR的Expression tree(4):创建静态类型的LINQ表达式树节点

    这篇博客文章“LINQ与DLR的Expression tree(4):创建静态类型的LINQ表达式树节点”深入探讨了如何构建这种数据结构,特别是关注静态类型的表达式树节点。 Expression Tree是一种表示方法调用、条件语句、算术运算...

    06.C# 知识回顾 - 表达式树 Expression Trees.pdf

    表达式树(Expression Trees)是.NET Framework中的一个重要概念,特别是与C#语言紧密相关。表达式树允许开发者以树状结构表示代码表达式。每棵树代表一个表达式,而树的节点代表表达式中的运算符、方法调用、参数等...

    C#基于表达式(Expression)实现对象深拷贝

    在C#中,`System.Linq.Expressions`命名空间提供了构建和操作表达式树的相关类。 对于深拷贝,我们通常会利用序列化和反序列化的方法,但这可能会导致性能损失,尤其是在处理大型对象或循环引用时。而使用表达式树...

    C#表达式树教程

    在C#编程中,表达式树(Expression Tree)是一种数据结构,它以树的形式表示了程序中的表达式。表达式树对于理解代码逻辑、编译器优化、动态代码执行以及 LINQ 查询等场景有着重要的作用。本教程将深入探讨表达式树...

    Expression表达式树动态查询.zip

    "Expression表达式树动态查询.zip"中的内容显然是关于如何使用C#表达式树来构建动态查询的示例或教程。 表达式树(Expression Tree)是将代码表示为树形结构,其中每个节点都是代码的一部分,如变量、操作符、方法...

    C# System.Linq.Expressions表达式序列化源码

    `System.Linq.Expressions`命名空间是C#中的一个关键部分,它允许开发者创建和操作表达式树,这是Linq背后的核心技术。 **表达式树**是C#中一种特殊的对象结构,它表示可执行的代码,就像一棵树形结构,每个节点都...

    动态构建Linq表达式

    1. **表达式树基础知识**:Linq表达式树是一种表示C#或VB.NET代码结构的数据结构。每个表达式节点都代表一个代码元素,如变量、方法调用、条件判断等。这些节点可以组合成复杂的表达式树,反映了代码的执行逻辑。 2...

    回答问答和论坛的几个小程序,包括了表达式树代替反射的例子等

    在C#编程中,表达式树(Expression Trees)和反射是两种重要的技术,它们在处理动态行为和元数据方面有着广泛的应用。本压缩包文件包含了多个小程序,这些程序旨在帮助开发者理解和运用这两种技术,特别是在回答问答...

    浅谈c#表达式树Expression简单类型比较demo

    在C#中,`System.Linq.Expressions`命名空间提供了处理表达式树的相关类。`Expression`类是构建表达式树的基本单元,它可以代表各种类型的C#表达式,如变量、常量、运算符、方法调用等。 在提供的代码示例中,我们...

    表达式树和泛型缓存完成Mapper效果

    在C#中,`System.Linq.Expressions`命名空间提供了处理表达式树的相关类。 利用表达式树,我们可以动态地构建和编译映射规则。例如,我们可以创建一个方法,接受两个类型参数(源类型和目标类型),然后构建一个...

    C#之Expression表达式树实例

    C#的Expression表达式树提供了一种灵活的方式来处理代码,不仅适用于LINQ查询,还适用于动态编译和运行代码、生成元编程解决方案等场景。通过理解表达式树的工作原理和构建方式,开发者可以更高效地编写出强大且灵活...

    C#简单实现表达式目录树(Expression)

    使用System.Linq.Expressions命名空间可以实现表达式目录树缓存,例如: ```csharp public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } ...

    Linq.Expression.Optimizer:System.Linq.Expression表达式优化器。 http:thorium.github.ioLinq.Expression.Optimizer

    然而, LINQ查询在执行时,其内部会转化为一系列的`System.Linq.Expressions.Expression`对象,这些表达式树代表了查询的逻辑结构。在某些情况下,为了提高性能,我们需要对这些表达式进行优化,这就是`Linq....

    五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树 - 文章 - 伯乐在线1

    表达式树(Expression Trees)在C#中用于表示代码的抽象语法树(AST)。它们是一种数据结构,将代码表示为节点树,每个节点代表代码的不同部分。表达式树常用于 LINQ 查询中,允许编译器分析和操作查询表达式。例如...

    在linq查询中使用反射

    2. 创建表达式树:LINQ查询的基础是表达式树(Expression Trees),它们是表示代码的抽象语法树。使用`Expression`类,你可以构建表示反射调用的表达式树。例如,`Expression.Call(null, typeof(YourType).GetMethod...

    ExpressionTreeVisualizer

    通过构建表达式树并用System.Linq.Expressions.Expression.Compile()方法编译,可以在运行时动态生成并执行代码。这在处理跨语言交互、数据库查询或动态业务规则时非常有用。 总的来说,“ExpressionTreeVisualizer...

    C#表达式目录树vs实用插件

    而在VS2017和VS2013中,可能有类似“Expression Tree Explorer”这样的工具,提供更加详细的表达式树节点信息和自定义视图。 学习C#表达式目录树的关键在于理解其基本节点类型,如LambdaExpression、...

Global site tag (gtag.js) - Google Analytics