C# - LINQ 表达式树
2021-05-08 06:26
标签:种类型 没有 有一个 each 基类 open lis 指定 linq 表达式树(Expression Tree) 表达式树是不可执行的代码,它只是用于表示一种树状的数据结构,树上的每一个节点都表示为某种表达式类型,大概有25种表达式类型,它们都派生自Expression类。创建表达式树具体有两个优势: 1.对表达式树的代码进行编辑修改,使表达式树中的代码变成动态代码,根据不同的数据库修改树上的代码逻辑从而达到动态切换数据库查询语句的目的,用表达式树可以动态构建针对不同数据库的查询语句。 2.完成类似反射访问未知对象的属性,通过动态构造表达式树,生成委托。 两种方式创建表达式树 Expression 此类的继承关系:Expression 此类利用Func委托指向的一个Lambda表达式,解析Lambda表达式的内容以便生成一棵具体的表达式树,可以将此类看成是封装表达式树的类型。注:这种方式创建表达式树时只能提供一个Lambda表达式,不能提供Lambda语句。所以如果需要创建复杂的表达式树,还是得使用Expression类的静态方法。 Expression(表达式树类) 此类表示为一棵表达式树。 无论是使用Expression
上面例子中创建了一个表达式( x , y ) => x != y && x!=0,主体是( x , y ) => x != y && x!=0,主体代码体是x != y && x!=0,&&是一个表达式,它含有左右两个操作数的子表达式,所以它会被拆分,左边x != y是一个表达式,右边 x!=0也是一个表达式,左右两边都含有子表达式,所以会继续拆分,直到无法拆分为止,结构如下:
Expression的子类 树的每个子节点是一个具体的表达式,它们都有自己的表达式类型,这些类型从Expression派生。 ExpressionType枚举 创建一个块语句表达式,在块中创建双重循环表达式的例子:
Linq查询中的表达式树 为什么有时候Linq查询需要表达式树? Linq To SQL Queryable类为IQueryable
//获取表达式树,返回一个Expression对象
Parameters
//获取Lambda表达式的参数,返回一个ReadOnlyCollection
//示例:
ExpressionFuncint , 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
//示例:
ExpressionFuncint , int , bool>> additionExpressionInfo = ( x , y ) => x != y && x != 0;
Console.WriteLine(expressionInfo.Type ); //print System.Func`2[System.Int32,System.Int32]
//返回Expression
//示例:
ExpressionFuncint , int , bool>> additionExpressionInfo = ( x , y ) => x != y && x != 0;
Funcint , int , bool> funcDeleg = additionExpressionInfo.Compile ( );
Console.WriteLine ( funcDeleg ( 1 , 2 ) ); //print true
//或
bool IsTrue = additionExpressionInfo.Compile ( ) ( 1 , 2 ); // true
//编译器会自动将Lambda表达式解析为Expression类型的表达式并为此生成一棵表达式树,再将这棵表达式树赋值给Expression
ExpressionFuncint,int>> ExpressionInfo = ( x ) => x;
//创建一个常量表达式,注: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
//通常情况下,使用此方法是为了调用一个表示方法调用的表达式或者调用一个块表达式
//如果你想执行表达式树的内容,比如执行表示方法调用的表达式则需要创建MethodCallExpression
//如果你想执行表达式树的内容,比如执行表示非方法调用的计算表达式则需要创建BlockExpression,
//所以,想要表达式得以执行,需要使用MethodCallExpression或BlockExpression定义可执行的表达式,然后使用Lambda ( )将该表达式转换为Expression
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 ) ) //方法的参数
);
ExpressionAction> action = Expression.LambdaAction> ( method );
action.Compile( ) ( ); // print 寒食
//假设要为这段代码创建表达式树:"hello world".ToUpper(),
Expression callExpr = Expression.Call (
Expression.Constant ( "hello world" ) , //有实例调用方法
typeof ( string ).GetMethod ( "ToUpper" , new Type [ ] { } )
);
string newStr = Expression.LambdaFuncstring>> ( 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
);
Funcint> func = Expression.LambdaFuncint>> ( block ).Compile ( );
Console.WriteLine(func ( ) ); // print 300
LessThanOrEqual
//创建一个BinaryExpression表示
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.LambdaFuncbool>> ( 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.LambdaAction>(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.LambdaFuncint>> ( block ).Compile ( ) ( );
Console.Write(r ); // print 10
Expression variableExpression = Expression.Variable ( typeof ( int ) , "x" );
ParameterExpression;
NewArrayExpression;
DefaultExpression;
DynamicExpression;
TypeBinaryExpression;
UnaryExpression;
BinaryExpression;
BlockExpression;
ConditionalExpression;
LoopExpression;
LabelExpression;
SwitchExpression;
TryExpression;
DebugInfoExpression;
MemberExpression;
IndexExpression;
InvocationExpression;
NewExpression;
MemberInitExpression;
MethodCallExpression;
LambdaExpression;
ListInitExpression;
//加法运算,如 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
LeftShiftAssign
//按位左移复合赋值运算,如 ( a
LessThan
//"小于"比较,如 ( a
LessThanOrEqual
//"小于或等于"比较,如 ( a
ListInit
//创建一个新的操作的 IEnumerable 对象,并对其进行初始化从列表中的元素,如 new List
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 中的说明。
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
//为真时执行
Expression.Block (
new [ ] { y } ,
Expression.Assign ( y , Expression.Constant ( 1 ) ) ,
//内层循环
Expression.Loop (
Expression.IfThenElse (
Expression.LessThanOrEqual ( y , x ) , // y
//为真时执行
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.LambdaAction> ( block ).Compile ( ) ( );
Linq To Object
Enumerable类为IEnumerable
C# - 学习总目录
C# - LINQ 表达式树
标签:种类型 没有 有一个 each 基类 open lis 指定 linq
原文地址:http://www.cnblogs.com/myrocknroll/p/7630080.html