码迷,mamicode.com
首页 > Windows程序 > 详细

C# - LINQ 表达式树

时间:2017-10-06 23:10:16      阅读:374      评论:0      收藏:0      [点我收藏+]

标签:种类型   没有   有一个   each   基类   open   lis   指定   linq   

表达式树(Expression Tree)

表达式树是不可执行的代码,它只是用于表示一种树状的数据结构,树上的每一个节点都表示为某种表达式类型,大概有25种表达式类型,它们都派生自Expression类。创建表达式树具体有两个优势:

1.对表达式树的代码进行编辑修改,使表达式树中的代码变成动态代码,根据不同的数据库修改树上的代码逻辑从而达到动态切换数据库查询语句的目的,用表达式树可以动态构建针对不同数据库的查询语句。

2.完成类似反射访问未知对象的属性,通过动态构造表达式树,生成委托。 

 

两种方式创建表达式树

Expression<TDelegate>(封装表达式树的类)

此类的继承关系:Expression<TDelegate> - LambdaExpression - Expression。Expression是作为所有表达式类型的基类。

技术分享
Body
//获取表达式树,返回一个Expression对象

Parameters
//获取Lambda表达式的参数,返回一个ReadOnlyCollection<ParameterExpression> 集合,该集合存储了每一个参数变量表达式,可通过索引对项进行检索
//示例:
Expression<Func<int , int , bool>> additionExpressionInfo = ( x , y ) => x != y && x != 0;
foreach (var pa in additionExpressionInfo.Parameters )
{
    Console.WriteLine(pa.Name );
}

NodeType
//节点的类型,一个ExpressionType枚举数,用来描述表达式的行为ReturnType
//Lambda表达式的返回类型
Type
//返回Expression<TDelegate>类型,
//示例:
Expression<Func<int , int , bool>> additionExpressionInfo = ( x , y ) => x != y && x != 0;
Console.WriteLine(expressionInfo.Type ); //print System.Func`2[System.Int32,System.Int32]
属性.property
//方法
 
Compile ( )
//返回Expression<Func<TDelegate>>中的Func<TDelegate>以便可以执行这个委托
//示例:
Expression<Func<int , int , bool>> additionExpressionInfo = ( x , y ) => x != y && x != 0;
Func<int , int , bool> funcDeleg = additionExpressionInfo.Compile ( );
Console.WriteLine ( funcDeleg ( 1 , 2 ) ); //print true
//或
bool IsTrue = additionExpressionInfo.Compile ( ) ( 1 , 2 ); // true

此类利用Func委托指向的一个Lambda表达式,解析Lambda表达式的内容以便生成一棵具体的表达式树,可以将此类看成是封装表达式树的类型。注:这种方式创建表达式树时只能提供一个Lambda表达式,不能提供Lambda语句。所以如果需要创建复杂的表达式树,还是得使用Expression类的静态方法。

//将一个Lambda表达式赋值给一个Expression<TDelegate>类型的变量
//编译器会自动将Lambda表达式解析为Expression类型的表达式并为此生成一棵表达式树,再将这棵表达式树赋值给Expression<TDelegate>.Body
Expression<Func<int,int>> ExpressionInfo =  ( x ) => x;

Expression(表达式树类)

此类表示为一棵表达式树。

技术分享
Constant ( )
//创建一个常量表达式,注:Expression会自动生成常量的名字
//示例:
//创建一个表示常量的表达式:string x="寒食"
Expression.Constant( "寒食",typeof(string) )  

Variable ( )
//创建一个ParameterExpression表示变量/参数变量表达式

Parameter ( )
//创建一个ParameterExpression表示变量/参数变量表达式
//示例:
Expression.Variable( typeof (int ) , "x" ); /*等同于*/ Expression.Parameter( typeof (int ) , "y" );

PostIncrementAssign ( )
//创建一个UnaryExpression表示自递增表达式,如Expression.PostIncrementAssign(x),表示x++,类似的有PostDecrementAssign表示自递减表达式

Assign ( )
//创建一个BinaryExpression表示赋值表达式,赋值表达式总是有左右两边的操作数
//示例:
BinaryExpression binaryExpression = Expression.Assign ( Expression.Variable ( typeof ( int ) , "x" ) , Expression.Constant ( 2 ) ); //左是x,右是2 int x=2
Console.WriteLine(binaryExpression.ToString ( ) ); //print int x=2

AddAssign ( )
//创建一个BinaryExpression表示加法表达式,加法表达式总是有左右两边的操作数
//试了一下必须将加法表达式放进BlockExpression中,否则无法创建,参看下面的Block ( )方法的演示

DivideAssign ( )
//创建一个BinaryExpression表示除法表达式,除法表达式总是有左右两边的操作数

Lambda ( )
//将一个Expression表达式转换为Expression<Func<TDelegate>> | Expression<Action<TDelegate>> | Expression<Action>
//通常情况下,使用此方法是为了调用一个表示方法调用的表达式或者调用一个块表达式
//如果你想执行表达式树的内容,比如执行表示方法调用的表达式则需要创建MethodCallExpression
//如果你想执行表达式树的内容,比如执行表示非方法调用的计算表达式则需要创建BlockExpression,
//所以,想要表达式得以执行,需要使用MethodCallExpression或BlockExpression定义可执行的表达式,然后使用Lambda ( )将该表达式转换为Expression<T>,再调用Expression<T>.Compile()将其转换为可执行的委托

Call ( Expression expression , MethodInfo method , params Expression [ ] methodParamters )
//创建一个MethodCallExpression表示调用某个方法的表达式,只有表示方法调用的表达式和块表达式可以执行
//方法调用有两种情况:1.对象调用方法 2.类型调用方法 比如:Animal a=new Animal(); a.Show()区别于Animal.Count()
//如果不是对象调用方法则第一个参数可提供null,否则第一个参数需要提供调用方法的对象,对象也必须是一个Expression
//示例:
//假设要为这段代码创建表达式树:Console.WriteLine( ),
MethodCallExpression method = Expression.Call (
    null , //无实例调用方法
    typeof ( Console ).GetMethod ( "WriteLine" , new Type [ ] { typeof ( string ) } ) , //方法调用的表达式
    Expression.Constant ( "寒食" , typeof ( string ) ) //方法的参数
);

Expression<Action> action = Expression.Lambda<Action> ( method );
action.Compile( ) ( ); // print 寒食

//假设要为这段代码创建表达式树:"hello world".ToUpper(),
Expression callExpr = Expression.Call (
    Expression.Constant ( "hello world" ) , //有实例调用方法
    typeof ( string ).GetMethod ( "ToUpper" , new Type [ ] { } )
);
string newStr = Expression.Lambda<Func<string>> ( callExpr ).Compile ( ) ( ); // HELLO WORLD

Block ( )
//创建一个BlockExpression表示块表达式,只有表示方法调用的表达式和块表达式可以执行
//示例:块中的表达式都是一步一步的定义出来的,创建块表达式时你可以想象一下在块中写C#代码块的流程,这样你就知道下面Block ( )方法的参数(表达式)是如何创建的了
ParameterExpression x = Expression.Parameter( typeof (int ) , "x" ); // int x
ParameterExpression y = Expression.Parameter ( typeof ( int ) , "y" ); // int y
BlockExpression block = Expression.Block (
    new ParameterExpression [ ] { x , y } , // int x,int y 定义块作用域中的变量表达式
    Expression.Assign ( x , Expression.Constant ( 100 ) ) , //x=100 定义块作用域中的赋值表达式
    Expression.Assign ( y , Expression.Constant ( 200 ) ) , //y =200 定义块作用域中的赋值表达式
    Expression.AddAssign ( x , y ) // var r = x + y
);
Func<int> func = Expression.Lambda<Func<int>> ( block ).Compile ( );
Console.WriteLine(func ( ) ); // print 300

LessThanOrEqual
//创建一个BinaryExpression表示<=的表达式,类似的有LessThan ( )

GreaterThanOrEqual ( )
//创建一个BinaryExpression表示>=的表达式,类似的有GreaterThan ( )
//示例:
var x = Expression.Parameter ( typeof ( int ) , "x" );
var y = Expression.Parameter ( typeof ( int ) , "y" );

var block = Expression.Block (
    new ParameterExpression [ ] { x , y } ,
    Expression.Assign ( x , Expression.Constant ( 100000 ) ) ,
    Expression.Assign ( y , Expression.Constant ( 200 ) ) ,
    Expression.LessThanOrEqual ( x , y )  // x >= y
);

bool IsTrue = Expression.Lambda<Func<bool>> ( block ).Compile ( ) ( );
Console.WriteLine(IsTrue ); // print true

IfThenElse ( Expression expressionForTest , Expression ifTestIsTrue , Expression ifTestIsFlase )
//创建一个ConditionalExpression表示条件语句表达式
//示例:
var x = Expression.Parameter ( typeof ( int ) , "x" );
var y = Expression.Parameter ( typeof ( int ) , "y" );

var block = Expression.Block (
    new ParameterExpression [ ] { x , y } ,
    Expression.Assign ( x , Expression.Constant ( 100000 ) ) ,
    Expression.Assign ( y , Expression.Constant ( 200 ) ) ,
    Expression.IfThenElse (
        Expression.GreaterThanOrEqual ( x , y ) , // if ( x >= y )
        Expression.Call ( null , typeof ( Console ).GetMethod ( "WriteLine" , new Type [ ] { typeof ( string ) } ) , Expression.Constant ( "x>y==true" ) ) , //条件为真时执行
        Expression.Call ( null , typeof ( Console ).GetMethod ( "WriteLine" , new Type [ ] { typeof ( string ) } ) , Expression.Constant ( "x>y==false" ) ) //条件为假时执行
    )

);

Expression.Lambda<Action>(block ).Compile ( ) ( ); // print x>y==true

Label ( )
//创建一个表示LabelTarget的标签,此标签常用于退出循环,将标签作为Loop ( )方法的最后一个参数,然后在某个条件中使用Expression.Break(LabelTarget )
//参看下面的Loop语句表达式

Break ( )
//退出循环,如果有嵌套循环,嵌套的循环内也得使用此方法来退出嵌套循环

Loop ( )
//创建一个LoopExpression表示循环语句表达式
//示例:
var label = Expression.Label ( typeof ( int ) );
var x = Expression.Variable ( typeof ( int ) , "x" );
var block = Expression.Block (
    new [ ] { x } ,
    Expression.Assign ( x , Expression.Constant ( 0 ) ) ,
    Expression.Loop (
        Expression.IfThenElse (
            Expression.LessThan (
                x ,
                Expression.Constant ( 10 )
            ) ,
            Expression.PostIncrementAssign ( x ) ,// x++
            Expression.Break ( label , x ) //将x作为标签的值
        ) ,
    label
    )
);
int r = Expression.Lambda<Func<int>> ( block ).Compile ( ) ( );
Console.Write(r ); // print 10
静态方法.staticMethod
//直接使用Expression的静态方法创建表达式树
Expression variableExpression = Expression.Variable ( typeof ( int ) , "x" );

无论是使用Expression<TDelegate>还是Expression的静态方法创建表达式,编译器都会自动为表达式生成一棵树结构,然后将表达式主体的代码体拆分成单一的表达式并作为主体表达式的子节点。变量、参数、运算符都会被拆分成一个单一的表达式,如果被拆分的表达式含有多个子表达式,则子表达式将作为表达式的子节并以此类推。上面例子中创建了一个表达式(x)=>x,(x)=>x就称为表达式树的主体,代码体是=>x,编译器自动将这个主体的代码体拆分为单一的表达式节点,因为该表达式主体的代码体只有一个表达式x,所以编译器在树上创建一个x表达式,结构如下:

技术分享

Expression<Func<int , int , bool>> additionExpressionInfo = ( x , y ) => x != y && x != 0;

上面例子中创建了一个表达式( x , y ) => x != y && x!=0,主体是( x , y ) => x != y && x!=0,主体代码体是x != y && x!=0,&&是一个表达式,它含有左右两个操作数的子表达式,所以它会被拆分,左边x != y是一个表达式,右边 x!=0也是一个表达式,左右两边都含有子表达式,所以会继续拆分,直到无法拆分为止,结构如下:

技术分享

Expression的子类

树的每个子节点是一个具体的表达式,它们都有自己的表达式类型,这些类型从Expression派生。

技术分享
ConstantExpression;
ParameterExpression;
NewArrayExpression
DefaultExpression;
DynamicExpression;
TypeBinaryExpression;
UnaryExpression;
BinaryExpression
BlockExpression
ConditionalExpression
LoopExpression
LabelExpression;
SwitchExpression;
TryExpression;
DebugInfoExpression;
MemberExpression;
IndexExpression;
InvocationExpression;
NewExpression
MemberInitExpression;
MethodCallExpression
LambdaExpression
ListInitExpression
/*派生自Expression的表达式类型*/

ExpressionType枚举

技术分享
Add
//加法运算,如 a + b, ,不进行溢出检查,针对数值操作数。
AddAssign
//加法复合赋值运算,如 ( a += b), ,不进行溢出检查,针对数值操作数。
AddAssignChecked
//加法复合赋值运算,如 ( a += b), ,进行溢出检查,针对数值操作数。
AddChecked
//加法运算,如 ( a + b), ,进行溢出检查,针对数值操作数。
And
//按位或逻辑 AND 操作,如 ( a & b) 在 C# 和 (a And b) 在 Visual Basic 中。
AndAlso
//在条件 AND 仅当第一个操作数的计算结果为才计算第二个操作数的操作 true。 它对应于 ( a && b) 在 C# 和 (a AndAlso b) 在 Visual Basic 中。
AndAssign
//按位或逻辑 AND 复合赋值运算,如 ( a &= b) C# 中。
ArrayIndex
//索引操作在一维数组中,如 array [ index ] 在 C# 或 array(index) 在 Visual Basic 中。
ArrayLength
//获取一维数组的长度,如操作 array.Length。
Assign
//赋值运算,如 (a = b )。
Block
//表达式的块。
Call
//某个方法调用,如在 obj.sampleMethod ( ) 表达式。
Coalesce
//一个表示空合并操作,如节点 ( a ?? b) 在 C# 或 If(a, b) 在 Visual Basic 中。
Conditional
//条件运算,如 a > b? a : b 在 C# 或 If(a > b, a, b) 在 Visual Basic 中。
Constant
//常量的值。
Convert
//强制转换或转换操作中,如 ( SampleType)obj C# 中或 CType(obj, SampleType) 在 Visual Basic 中。 对于数值的转换,如果转换后的值对于目标类型来说太大不引发异常。
ConvertChecked
//强制转换或转换操作中,如 ( SampleType)obj C# 中或 CType(obj, SampleType) 在 Visual Basic 中。 对于数值的转换,如果转换后的值不符合目标类型是引发异常。
DebugInfo
//调试信息。
Decrement
//一元递减操作,如 ( a - 1) C# 和 Visual Basic 中。 该对象 a 不应就地修改。
Default
//默认值。
Divide
//除法运算,如 ( a / b), ,针对数值操作数。
DivideAssign
//除的复合赋值运算,如 ( a /= b), ,针对数值操作数。
Dynamic
//动态操作。
Equal
//一个表示相等比较,如节点 ( a == b) 在 C# 或 (a = b) 在 Visual Basic 中。
ExclusiveOr
//按位或逻辑 XOR 操作,如 ( a ^ b) 在 C# 或 (a Xor b) 在 Visual Basic 中。
ExclusiveOrAssign
//按位或逻辑 XOR 复合赋值运算,如 ( a ^= b) C# 中。
Extension
//扩展表达式。
Goto
//一个"转到"表达式,如 goto Label 在 C# 或 GoTo Label 在 Visual Basic 中。
GreaterThan
//"大于"比较,如 ( a > b)。
GreaterThanOrEqual
//"大于或等于"比较,如 ( a >= b)。
Increment
//一元递增操作,如 ( a + 1) C# 和 Visual Basic 中。 该对象 a 不应就地修改。
Index
//索引操作或访问不采用参数的属性的操作。
Invoke
//操作调用的委托或 lambda 表达式,如 sampleDelegate.Invoke ( )。
IsFalse
//一个 false 条件值。
IsTrue
//一个 true 条件值。
Label
//标签。
Lambda
//Lambda 表达式,如 a => a + a 在 C# 或 Function(a) a + a 在 Visual Basic 中。
LeftShift
//按位左移运算,如 ( a << b)。
LeftShiftAssign
//按位左移复合赋值运算,如 ( a <<= b)。
LessThan
//"小于"比较,如 ( a<b)。
LessThanOrEqual
//"小于或等于"比较,如 ( a <= b)。
ListInit
//创建一个新的操作的 IEnumerable 对象,并对其进行初始化从列表中的元素,如 new List<SampleType>(){ a, b, c } 在 C# 或 Dim sampleList = { a, b, c } 在 Visual Basic 中。
Loop
//一个循环,如 for 或 while。
MemberAccess
//从一个字段或属性,如读取操作 obj.SampleProperty。
MemberInit
//运算,创建一个新的对象并初始化一个或多个成员,如 new Point { X = 1, Y = 2 } 在 C# 或 New Point With {.X = 1, .Y = 2} 在 Visual Basic 中。
Modulo
//算术余数运算,如 ( a % b) 在 C# 或 (a Mod b) 在 Visual Basic 中。
ModuloAssign
//算术余数复合赋值运算,如 ( a %= b) C# 中。
Multiply
//乘法运算,如 ( a* b ), ,不进行溢出检查,针对数值操作数。
MultiplyAssign
//乘法复合赋值运算,如 ( a *= b), ,不进行溢出检查,针对数值操作数。
MultiplyAssignChecked
//乘法复合赋值运算,如 ( a *= b), ,,进行溢出检查,针对数值操作数。
MultiplyChecked
//乘法运算,如 ( a* b ), ,,进行溢出检查,针对数值操作数。
Negate
//算术求反运算,如 (-a)。 该对象 a 不应就地修改。
NegateChecked
//算术求反运算,如 (-a), ,,进行溢出检查。 该对象 a 不应就地修改。
New
//调用构造函数以创建新的对象,如操作 new SampleType()。
NewArrayBounds
//创建一个新数组,其中每个维度的下限指定,如操作 new SampleType[dim1, dim2] 在 C# 或 New SampleType(dim1, dim2) 在 Visual Basic 中。
NewArrayInit
//操作,创建一个新的一维数组并对其进行初始化从列表中的元素,如 new SampleType[]{a, b, c} 在 C# 或 New SampleType(){a, b, c} 在 Visual Basic 中。
Not
//按位求补或逻辑求反运算。 在 C# 中,则等同于 (~a) 整型和 (!a) 布尔值。 在 Visual Basic 中,则等同于 (Not a)。 该对象 a 不应就地修改。
NotEqual
//不相等比较,如 (a != b) 在 C# 或 (a <> b) 在 Visual Basic 中。
OnesComplement
//一个二进制反码运算,如 (~a) C# 中。
Or
//按位或逻辑 OR 操作,如 (a | b) 在 C# 或 (a Or b) 在 Visual Basic 中。
OrAssign
//按位或逻辑 OR 复合赋值运算,如 (a |= b) C# 中。
OrElse
//短路条件 OR 操作,如 (a || b) 在 C# 或 (a OrElse b) 在 Visual Basic 中。
Parameter
//对参数或变量的表达式的上下文中定义的引用。 有关更多信息,请参见ParameterExpression。
PostDecrementAssign
//一元后缀递减,如 (a--)。 该对象 a 应就地修改。
PostIncrementAssign
//一元后缀递增,如 (a++)。 该对象 a 应就地修改。
Power
//如引发数字进行幂运算的数学运算 (a ^ b) 在 Visual Basic 中。
PowerAssign
//如引发数字进行幂运算的复合赋值运算 (a ^= b) 在 Visual Basic 中。
PreDecrementAssign
//一元前缀递减,如 (--a)。 该对象 a 应就地修改。
PreIncrementAssign
//一元前缀递增,如 (++a)。 该对象 a 应就地修改。
Quote
//具有类型的常量值的表达式 Expression。 一个 Quote 节点可以包含对它所代表的表达式的上下文中定义的参数的引用。
RightShift
//按位右移运算,如 (a >> b)。
RightShiftAssign
//按位右移复合赋值运算,如 (a >>= b)。
RuntimeVariables
//运行时变量的列表。 有关详细信息,请参阅RuntimeVariablesExpression。
Subtract
//减法运算,如 (a - b), ,不进行溢出检查,针对数值操作数。
SubtractAssign
//减法复合赋值运算,如 (a -= b), ,不进行溢出检查,针对数值操作数。
SubtractAssignChecked
//减法复合赋值运算,如 (a -= b), ,,进行溢出检查,针对数值操作数。
SubtractChecked
//算术减法运算,如 (a - b), ,,进行溢出检查,针对数值操作数。
Switch
//一个切换操作,如 switch 在 C# 或 Select Case 在 Visual Basic 中。
Throw
//引发异常,如操作 throw new Exception()。
Try
//一个 try-catch 表达式。
TypeAs
//显式引用或装箱转换在其中 null 如果转换失败,如提供 (obj as SampleType) 在 C# 或 TryCast(obj, SampleType) 在 Visual Basic 中。
TypeEqual
//确切类型测试。
TypeIs
//一种类型测试,如 obj is SampleType 在 C# 或 TypeOf obj is SampleType 在 Visual Basic 中。
UnaryPlus
//一元正运算,如 (+a)。 预定义的一元正运算的结果是操作数的值,但用户定义的实现可能有不寻常的结果。
Unbox
//取消装箱值类型的操作,如 unbox 和 unbox.any MSIL 中的说明。
/*节点的NodeType用以描述表达式的行为*/

创建一个块语句表达式,在块中创建双重循环表达式的例子:

LabelTarget outerBreak = Expression.Label ( );
LabelTarget innerBreak = Expression.Label ( );
var x = Expression.Variable ( typeof ( int ) , "x" );
var y = Expression.Variable ( typeof ( int ) , "y" );
var result = Expression.Variable ( typeof ( int ) , "result" );

var block = Expression.Block (
    new [ ] { x } ,
    Expression.Assign ( x , Expression.Constant ( 1 ) ) ,
    //循环
    Expression.Loop (
        //条件判断
        Expression.IfThenElse (
            //如果表达式为真
            Expression.LessThan ( x , Expression.Constant ( 10 ) ) , // if x<10
                                                                        //为真时执行
            Expression.Block (
                new [ ] { y } ,
                Expression.Assign ( y , Expression.Constant ( 1 ) ) ,
                //内层循环
                Expression.Loop (
                    Expression.IfThenElse (
                        Expression.LessThanOrEqual ( y , x ) , // y <= x
                                                                //为真时执行
                        Expression.Block (
                            new [ ] { result } ,
                            Expression.Assign ( result , Expression.Multiply ( x , y ) ) ,
                            Expression.Call ( null , typeof ( Console ).GetMethod ( "Write" , new Type [ ] { typeof ( int ) } ) , y ) ,
                            Expression.Call ( null , typeof ( Console ).GetMethod ( "Write" , new Type [ ] { typeof ( string ) } ) , Expression.Constant ( "×" ) ) ,
                            Expression.Call ( null , typeof ( Console ).GetMethod ( "Write" , new Type [ ] { typeof ( int ) } ) , x ) ,
                            Expression.Call ( null , typeof ( Console ).GetMethod ( "Write" , new Type [ ] { typeof ( string ) } ) , Expression.Constant ( "=" ) ) ,
                            Expression.Call ( null , typeof ( Console ).GetMethod ( "Write" , new Type [ ] { typeof ( int ) } ) , result ) ,
                            Expression.Call ( null , typeof ( Console ).GetMethod ( "Write" , new Type [ ] { typeof ( string ) } ) , Expression.Constant ( "\t" ) ) ,
                            Expression.PostIncrementAssign ( y ) // y++
                        ) ,
                        //为假时退出内层循环
                        Expression.Break ( innerBreak )
                    ) ,
                    innerBreak
                ) ,//内层循环end
                Expression.Call ( null , typeof ( Console ).GetMethod ( "WriteLine" , new Type [ ] { typeof ( string ) } ) , Expression.Constant ( "" ) ) ,
                Expression.PostIncrementAssign ( x ) // x++
            ) ,
            //为假时执行
            Expression.Break ( outerBreak )
            )
    , outerBreak )
);

Expression.Lambda<Action> ( block ).Compile ( ) ( );

技术分享

 

Linq查询中的表达式树

为什么有时候Linq查询需要表达式树?

Linq To SQL

Queryable类为IQueryable<T>实现了一系列的扩展方法用于Linq To SQL的查询,这些扩展方法大部分都返回一个IQueryable<T>类型,IQueryable <T>有一个Expression类型的属性叫做Expression,当使用Linq To SQL执行Linq查询时会调用那些扩展方法,而扩展方法都要求一个Expression<T>类型的参数,扩展方法接收这个作为参数的表达式树后将它作为IQueryable <T>集合的Expression属性来使用,IQueryable <T>还有一个叫做IQueryProvider(Linq查询提供程序)的属性,IQueryProvider类拿到Expression表达式树后会对其进行解剖以便生成纯SQL语句,再将SQL字符串发送到数据库以便执行。所以从此处可以看出来,表达式树具有很高的灵活性,它并非可执行的C#代码,但通过Expression提供的一系列属性和方法,你可以对其进行解剖,根据需求的不同从而动态修改表达式树中的表达式以便生成可在非C#环境执行的代码。说白了创建表达式树是为了在运行时将树上的逻辑解析为你期望的目标代码,这一切都通过Expression来实现,决定权在你手里。

Linq To Object

Enumerable类为IEnumerable<T>实现了一系列的扩展方法用于Linq To Object的查询,这些扩展方法大部分都返回一个IEnumerable<T>类型,IEnumerable<T>没有需要接收表达式树作为参数的扩展方法,因为Linq To Object是直接查询内存中的数据,不需要转化为SQL语句,所以根本用不上表达式树。

 

C# - 学习总目录

C# - LINQ 表达式树

标签:种类型   没有   有一个   each   基类   open   lis   指定   linq   

原文地址:http://www.cnblogs.com/myrocknroll/p/7630080.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!