【C#表达式树 五】工厂模式创建表达式树节点
常量
1、值常量 (p)=>100+88+p
ParameterExpression par = Expression.Parameter(typeof(int), "p"); BinaryExpression binaryexp = Expression.Add(Expression.Constant(100), Expression.Constant(88));//值类型常数 BinaryExpression parAndi = Expression.Add(binaryexp, par); LambdaExpression m2 = Expression.Lambda(parAndi, par);//LambdaExpression.Compile() 方法返回 Delegate 类型。 必须将其转换为正确的委托类型,执行的效率非常慢,不如泛型 Console.WriteLine(m2.Compile().DynamicInvoke(2));//执行的效率非常慢,不如泛型
2、字符串常量 ()=>"100"+"88"
构造类型为LambdaExpression的lambda表达式树,编译后得到委托的基元类型(弱类型)。
MethodInfo mInfo = typeof(String).GetMethod("Concat", new Type[] { typeof(String), typeof(String) });//第一步:获取Concat方法的MethodInfo BinaryExpression binaryexp = Expression.Add(Expression.Constant("100"), Expression.Constant("88"), mInfo);//将方法传递给 Expression.Add LambdaExpression lb = Expression.Lambda(binaryexp); Console.WriteLine(lb.Compile().DynamicInvoke());//执行的效率非常慢,不如泛型
但这时会报错 “没有为类型“System.String”和“System.String”定义二进制运算符 Add”,这是怎么回事,在我们代码时如果写 string s= "100"+"88";是没错的啊。实际上字串的 + 在生成IL代码时,会转换成 string 的 Concat 扩展方法来操作。因此要实现如 "100"+"88" 还是稍显麻烦
第一步:获取Concat方法的MethodInfo
第二步:将方法传递给 Expression.Add
变量
//Assign 创建一个表示赋值运算的 BinaryExpression。
void AssignSample()
{
ParameterExpression variableAssignExpr = Expression.Variable(typeof(String), "sampleVar");
Expression assignSimpleExpr = Expression.Assign(
variableAssignExpr,
Expression.Constant("Hello World!")
);
Expression blockAssignExpr = Expression.Block(
new ParameterExpression[] { variableAssignExpr },
assignSimpleExpr
);
Console.WriteLine(assignSimpleExpr.ToString());//(sampleVar = "Hello World!")
Console.WriteLine(Expression.Lambda<Func<String>>(blockAssignExpr).Compile()());//Hello World!
}
AssignSample();
创建数组
NewArrayInit 创建一个表示创建一维数组并使用元素列表初始化该数组的 NewArrayExpression
//NewArrayInit 创建一个表示创建一维数组并使用元素列表初始化该数组的 NewArrayExpression。
void NewArrayInitSample()
{
List<Expression> trees = new List<Expression>() {
Expression.Constant("oak"),
Expression.Constant("fir"),
Expression.Constant("spruce"),
Expression.Constant("alder")
};
NewArrayExpression newArrayExpression = Expression.NewArrayInit(typeof(string), trees);
newArrayExpression.ToString().Dump("NewArrayInit");
}
NewArrayInitSample();
NewArrayBounds 创建一个表示创建具有指定秩的数组的 NewArrayExpression
//NewArrayBounds 创建一个表示创建具有指定秩的数组的 NewArrayExpression。
void NewArrayBoundsSample()
{
NewArrayExpression newArrayExpression = Expression.NewArrayBounds(
typeof(string),
Expression.Constant(3),
Expression.Constant(2)
);
newArrayExpression.ToString().Dump("NewArrayBounds");//new System.String[,](3, 2)
}
NewArrayBoundsSample();
类型转换
算术运算符
Add(Expression, Expression) 创建一个表示不进行溢出检查的算术加法运算的
public class Plus { //下面表达式指定加法的实现 public static int AddOne(int a, int b) { return a + b + 1; } } //Add(Expression, Expression) 创建一个表示不进行溢出检查的算术加法运算的 BinaryExpression。 void AddSample() { Expression sumExpr = Expression.Add(Expression.Constant(1), Expression.Constant(2)); Console.WriteLine(sumExpr.ToString());//(1+2) Console.WriteLine(Expression.Lambda<Func<int>>(sumExpr).Compile()());//3 Expression sumExpr2 = Expression.Add(Expression.Constant(1), Expression.Constant(2), typeof(Plus).GetMethod("AddOne")); Console.WriteLine(sumExpr2.ToString()); Console.WriteLine(Expression.Lambda<Func<int>>(sumExpr2).Compile()()); } AddSample();
Expression.Coalesce
xiaoli ?? xiaoi
BinaryExpression bin = Expression.Coalesce(Expression.Parameter(typeof(string), "xiaoli"), Expression.Parameter(typeof(string), "xiaoi"));
引用地址 Expression.ReferenceEqual Expression.ReferenceNotEqual
BinaryExpression bin2 = Expression.ReferenceEqual(Expression.Parameter(typeof(string), "xiaoli"), Expression.Parameter(typeof(string), "xiaoi")); BinaryExpression bin = Expression.ReferenceNotEqual(Expression.Parameter(typeof(string), "xiaoli"), Expression.Parameter(typeof(string), "xiaoi"));
赋值运算符
ParameterExpression i = Expression.Parameter(typeof(int), "i"); BlockExpression block = Expression.Block( new[] { i }, //赋初值 i=5 Expression.Assign(i, Expression.Constant(5, typeof(int))), //i+=5 10 Expression.AddAssign(i, Expression.Constant(5, typeof(int))), //i-=5 5 Expression.SubtractAssign(i, Expression.Constant(5, typeof(int))), //i*=5 25 Expression.MultiplyAssign(i, Expression.Constant(5, typeof(int))), //i/=5 5 Expression.DivideAssign(i, Expression.Constant(5, typeof(int))) ); Console.WriteLine(Expression.Lambda<Func<int>>(block).Compile()());
Assign 创建一个表示赋值运算的 BinaryExpression。
//Assign 创建一个表示赋值运算的 BinaryExpression。 void AssignSample() { ParameterExpression variableAssignExpr = Expression.Variable(typeof(String), "sampleVar"); Expression assignSimpleExpr = Expression.Assign( variableAssignExpr, Expression.Constant("Hello World!") ); Expression blockAssignExpr = Expression.Block( new ParameterExpression[] { variableAssignExpr }, assignSimpleExpr ); Console.WriteLine(assignSimpleExpr.ToString());//(sampleVar = "Hello World!") Console.WriteLine(Expression.Lambda<Func<String>>(blockAssignExpr).Compile()());//Hello World! } AssignSample();
AddAssign(Expression, Expression) 创建一个表示不进行溢出检查的加法赋值运算的 BinaryExpression
//AddAssign(Expression, Expression) 创建一个表示不进行溢出检查的加法赋值运算的 BinaryExpression void AddAssignSample() { ParameterExpression variableExpr = Expression.Variable(typeof(int), "sampleVar");//the parameter expression is used to create a variable; BlockExpression addAssignExpr = Expression.Block( new ParameterExpression[] { variableExpr }, Expression.Assign(variableExpr, Expression.Constant(1)), Expression.AddAssign( variableExpr, Expression.Constant(2) ) ); addAssignExpr.Expressions.ForEach(p => p.ToString().Dump());//(sampleVar = 1),(sampleVar +=2) Console.WriteLine(Expression.Lambda<Func<int>>(addAssignExpr).Compile()());//3 } AddAssignSample();
AddAssign(Expression, Expression, MethodInfo) 创建一个表示不进行溢出检查的加法赋值运算的 BinaryExpression。可指定实现
//AddAssign(Expression, Expression, MethodInfo) 创建一个表示不进行溢出检查的加法赋值运算的 BinaryExpression。可指定实现 //参Add(Expression, Expression, MethodInfo) //AddAssign(Expression, Expression, MethodInfo, LambdaExpression) 创建一个表示不进行溢出检查的加法赋值运算的 BinaryExpression。可指定实现, 可指定类型转换函数
AddAssignChecked(Expression, Expression) 创建一个表示进行溢出检查的加法赋值运算的 BinaryExpression。
//AddAssignChecked(Expression, Expression) 创建一个表示进行溢出检查的加法赋值运算的 BinaryExpression。 void AddAssignCheckedSample() { ParameterExpression variableExprWithChecked = Expression.Variable(typeof(int), "sampleVar");//the parameter expression is used to create a variable; BlockExpression addAssignExprWithChecked = Expression.Block( new ParameterExpression[] { variableExprWithChecked }, Expression.Assign(variableExprWithChecked, Expression.Constant(2147483647)), Expression.AddAssign( variableExprWithChecked, Expression.Constant(1) ) ); addAssignExprWithChecked.Expressions.ForEach(p => p.ToString().Dump());//(sampleVar = 2147483647),(sampleVar +=1) Console.WriteLine(Expression.Lambda<Func<int>>(addAssignExprWithChecked).Compile()());//-2147483648 } AddAssignCheckedSample(); //AddChecked(Expression, Expression) 创建一个表示进行溢出检查的算术加法运算的 BinaryExpression。 //同Add
NotEqual 创建一个表示不相等比较的 BinaryExpression。
//NotEqual 创建一个表示不相等比较的 BinaryExpression。
void NotEqualSample()
{
Expression notEqualExpr = Expression.NotEqual(Expression.Constant(1), Expression.Constant(2));
notEqualExpr.ToString().Dump("NotEqualExpr");//(1!=2)
Expression.Lambda<Func<bool>>(notEqualExpr).Compile()().Dump("NotEqual");//true
}
NotEqualSample();
//OnesComplement 返回表示一的补数的表达式。//TODO
关系运算符
逻辑运算符
Not 创建一个表示按位求补运算的 UnaryExpression。
//Not 创建一个表示按位求补运算的 UnaryExpression。 void NotSample() { Expression notExpr = Expression.Not(Expression.Constant(true)); notExpr.ToString().Dump("NotExpr");//Not(true) Expression.Lambda<Func<bool>>(notExpr).Compile()().Dump("Not");//false } NotSample();
调用方法
调用静态方法,构建表达式树:(x,y)=>Math.Sin(x)+Math.Cos(y)
ParameterExpression ParmsX=Expression.Parameter(typeof(double),"x"); //参数X ParameterExpression ParmsY=Expression.Parameter(typeof(double ),"y"); //参数Y var left=Expression.Call(typeof(Math).GetMethod("Sin"),ParmsX); //树左边节点 var right=Expression.Call(null,typeof(Math).GetMethod("Cos"),ParmsY);//调用静态方法这样写也可以,树右边节点 var body=Expression.Add(left,right); //合成表达式树主体 LambdaExpression lambda=Expression.Lambda<Func<double,double,double>>(body,new ParameterExpression []{ParmsX,ParmsY}); //转成的表达式树,在编译后,就可以调用委托所指向的方法。
调用实例方法,
ParameterExpression x =Expression.Parameter(typeof(string), "x"); Expression body = Call( x, typeof(string).GetMethod("StartsWith", new[] { typeof(string) })!, Constant("a")); Expression<Func<string, bool>> expr = Expression.Lambda<Func<string, bool>>(body, x);
Block
block相当于匿名函数,其返回表达式是最后一个表达式决定。如果有变量,那么就要通过new[]{变量}传入变量,再嵌套的block中可以使用外部的的变量,例如for 功能中的示例
无变量block
.Block() {
.Call System.Console.Write("你好!");
.Call System.Console.WriteLine("BlockExpression表达式!");
42;
.Call System.String.Concat("测试1 ","测试2")
}
//声明一个包含有4个表达式的表达式块。 BlockExpression blockExpr = Expression.Block( Expression.Call(null, typeof(Console).GetMethod("Write", new Type[] { typeof(String) }), Expression.Constant("你好!")),// 1 Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }),Expression.Constant("BlockExpression表达式!")),
Expression.Constant(42), Expression.Call(null, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }), Expression.Constant("测试1 "), Expression.Constant("测试2")) //4 ); Console.WriteLine("***********************"); Console.WriteLine("显示表达示块的执行结果:"); // 首先创建表达式树, // 编译,执行. var result2 = Expression.Lambda<Func<string>>(blockExpr).Compile(); result2(); var result = Expression.Lambda<Func<string>>(blockExpr).Compile()();
有参数block,block相当于匿名函数,如果有变量,那么就要通过new[]{变量}传入变量,由于是匿名函数 所以也会有返回值,返回值就是最有一个表达式的值
.Block(System.String $name, System.String $fomt)
{
$fomt = "名字:{0}";
$name = "xiaoli";
.Call System.String.Format( $fomt,$name)
}
ParameterExpression pa = Expression.Parameter(typeof(string), "name"); ParameterExpression ex = Expression.Parameter(typeof(string), "fomt"); BlockExpression blo = Expression.Block( //块内不能定义参数 类似这样是错误的 ParameterExpression ex = Expression.Parameter(typeof(string), "fomt"); new[] { pa, ex }, Expression.Assign(ex, Expression.Constant("名字:{0}")), Expression.Assign(pa,Expression.Constant("xiaoli" )), Expression.Call(typeof(string).GetMethod("Format",new[] { typeof(string),typeof(string)}),ex,pa) ); Console.WriteLine(Expression.Lambda(blo).Compile().DynamicInvoke() );
判断语句
三目运算符(Expression.Condition):?: 的应用 由于不是block那样的函数,所以可以直接使用外部的parameter定义的变量
() => {
int a;
int b;
a = 10;
b = 30;
return a == b ? "a和b相等" : "a与b不相等";//这个就是Expression.Condition
}将以上格式转换化成 表达式树 如下:
ParameterExpression aiP1 = Expression.Parameter(typeof(int), "a"); //(1) ParameterExpression aiP2 = Expression.Parameter(typeof(int), "b"); ParameterExpression aiP3 = Expression.Parameter(typeof(int)); Console.WriteLine(aiP3.ToString()); //输出:Param_0 BinaryExpression aiBnExp = Expression.MakeBinary(ExpressionType.Equal, aiP1, aiP2); ConditionalExpression aiCdExp = Expression.Condition( aiBnExp, Expression.Constant("a和b相等"), Expression.Constant("a与b不相等") ); //(2) Console.WriteLine(aiCdExp.ToString()); //输出:IIF((a == b), "a和b相等", "a与b不相等") LambdaExpression aiLamExp = Expression.Lambda( Expression.Block //(3) ( new ParameterExpression[] { aiP1, aiP2 } , Expression.Assign(aiP1, Expression.Constant(10)) , Expression.Assign(aiP2, Expression.Constant(30)) , aiCdExp )); Console.WriteLine(aiLamExp.Compile().DynamicInvoke()); Console.ReadLine();
2、Expression.IfThen
代码的效果如下:
.If ( $i % 2 == 0)
{
.Call System.Console.WriteLine($i)
}
ParameterExpression i = Expression.Parameter(typeof(int), "i");
ConditionalExpression con= Expression.IfThen(
Expression.Equal( Expression.Modulo(i, Expression.Constant(2, typeof(int))), Expression.Constant(0, typeof(int))),
Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), new[] { i })
);
3、Expression.IfThenElse
样式如下
if (value > 1) {
result *= value--;
} else {
result %= value--;
}
写成代码
ParameterExpression value = Expression.Parameter(typeof(int), "value"); //本地变量 ParameterExpression result = Expression.Parameter(typeof(int), "result"); ConditionalExpression ifthenelse= Expression.IfThenElse( Expression.GreaterThan(value, Expression.Constant(1)), Expression.MultiplyAssign(result, Expression.PostDecrementAssign(value)), Expression.ModuloAssign(result, Expression.PostDecrementAssign(value)));
4、for循环的实现
Expression<Action> lambdaExpression2 = () =>
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine("Hello");
}
};
再expression tree visual看到的效果
() => {
int index;
index = 1;
while (true) {
if (index <= 10) {
Console.WriteLine("Hello");
index++;
} else {
break;
}
};
}
LabelTarget labelBreak = Expression.Label(); ParameterExpression loopIndex = Expression.Parameter(typeof(int), "index"); BlockExpression block = Expression.Block( new[] { loopIndex }, // 初始化loopIndex =1 Expression.Assign(loopIndex, Expression.Constant(1)), Expression.Loop( Expression.IfThenElse( // if 的判断逻辑 Expression.LessThanOrEqual(loopIndex, Expression.Constant(10)), // 判断逻辑通过的代码 Expression.Block( Expression.Call( null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), Expression.Constant("Hello")), Expression.PostIncrementAssign(loopIndex)), // 判断不通过的代码 Expression.Break(labelBreak) ),labelBreak)); // 将我们上面的代码块表达式 Expression<Action> lambdaExpression = Expression.Lambda<Action>(block); lambdaExpression.Compile().Invoke();
5、SwitchExpression:
表示一个控制表达式,该表达式通过将控制传递到 SwitchCase 来处理多重选择。
//构建类似下列代码的表达式 //int i = 1; //switch (i) //{ // case 1: // Console.WriteLine("一等奖"); // break; // case 2: // Console.WriteLine("二等奖"); // break; // case 3: // Console.WriteLine("三等奖"); // break; // default: // Console.WriteLine("鼓励奖"); // break; //}
/声明 SwitchCase 的称值参数,相当于 switch (i) ParameterExpression aiSwvP = Expression.Parameter(typeof(int), "i"); //构造 SwitchExpression aiSwvExp = Expression.Switch( aiSwvP // switch (i) , Expression.Call( null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }), Expression.Constant("鼓励奖") ) //default 默认事例,此参数没有代码无默认事例 , new SwitchCase[] { //事例 之一,前部分是执行,后部分是合符条件值(与) Expression.SwitchCase( Expression.Call( null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }), Expression.Constant("一等奖") ) , Expression.Constant(1) //case 1 ) ,Expression.SwitchCase( Expression.Call( null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }), Expression.Constant("二等奖") ), Expression.Constant(2) //case 2 ) ,Expression.SwitchCase( Expression.Call( null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }), Expression.Constant("三等奖") ) ,Expression.Constant(3) //case 3 ) }); // The following statement first creates an expression tree, // then compiles it, and then runs it. Expression.Lambda<Action>(switchExpr).Compile()(); Expression.Lambda<Action<int>>(aiSwvExp, aiSwvP).Compile().DynamicInvoke(2);
循环语句
(
int result,
result = 1,
while (true) {
if (value > 1) {
result *= value--;
} else {
break result;
}
}
)
以下完成这个语句块。 该语句快默认是 while (true) 所以要跳出循环的语句。
//参数value ParameterExpression value = Expression.Parameter(typeof(int), "value"); //本地变量 ParameterExpression result = Expression.Parameter(typeof(int), "result"); //标签,用来跳出循环 LabelTarget label = Expression.Label(typeof(int)); //创建表达式块 BlockExpression block = Expression.Block( //添加本地参数result new[] { result }, //result=1 赋值 Expression.Assign(result, Expression.Constant(1)), //循环 Expression.Loop( //循环条件 Expression.IfThenElse( //如果 value>1 Expression.GreaterThan(value, Expression.Constant(1)), //则 result*=value--; Expression.MultiplyAssign(result, Expression.PostDecrementAssign(value)), //否则跳出loop循环。跳到label的语句执行 Expression.Break(label, result)//跳出循环并且 返回值 result ), label ) ); //编译表达式树 Func<int, int> factor = Expression.Lambda<Func<int, int>>(block, value).Compile(); //执行,输出结果120 Console.WriteLine(factor(5));
分析:句法 public static LoopExpression Loop(Expression body, LabelTarget? @break);
body :表达式主体 @break:推出的位置
public static ConditionalExpression IfThenElse(Expression test, Expression ifTrue, Expression ifFalse);
异常处理try 块中的 catch 语句
CatchBlock类:表示 try 块中的 catch 语句。
单独的CatchBlock是没有意义的,他必需和TryExpression一起使用才有用。
TryExpression类:表示 try/catch/finally/fault 块。
构建如下表达式:(try {} Catch {})
TryExpression tryCatchExpr = Expression.TryCatch( Expression.Block( Expression.Divide(Expression.Constant(50), Expression.Constant(2)), Expression.Constant("无异常返回") ), Expression.Catch( typeof(DivideByZeroException), Expression.Constant("异常返回") ) ); Console.WriteLine(Expression.Lambda<Func<string>>(tryCatchExpr).Compile()()); //输出为 :无异常返回 将上面的 Expression.Constant(2),更改为 Expression.Constant(0)
如果无法判断异常类型,刚将typeof(DivideByZeroException),换成 typeof(Exception);
如要增加 Finally,则用 TryCatchFinally 构建:
TryExpression tryCatchExpr2 = Expression.TryCatchFinally( Expression.Block( Expression.Divide(Expression.Constant(50), Expression.Constant(2)), Expression.Constant("无导常返回") ), Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), Expression.Constant("Finally 块")), Expression.Catch(typeof(Exception), Expression.Constant("导常返回") ) ); Console.WriteLine(Expression.Lambda<Func<string>>(tryCatchExpr2).Compile()());
UnaryExpression :表示包含一元运算符的表达式。
如:
UnaryExpression aiU1 = Expression.Negate(Expression.Constant(100)); Console.WriteLine(aiU1.ToString()); //Not(Ture) UnaryExpression aiU2 = Expression.Not(Expression.Constant(true)); Console.WriteLine(aiU2.ToString()); //() => 123456 UnaryExpression aiU3 = Expression.Quote(Expression.Lambda( Expression.Constant(123456))); Console.WriteLine(aiU3.ToString()); //(123456 As Nullable`1) UnaryExpression aiU4 = Expression.TypeAs(Expression.Constant(123456), typeof(int?)); Console.WriteLine(aiU4.ToString()); //Convert(123456) UnaryExpression aiU5 = Expression.Convert(Expression.Constant(123456), typeof(Int16)); Console.WriteLine(aiU5.ToString()); //+123456 UnaryExpression aiU6 = Expression.UnaryPlus(Expression.Constant(123456)); Console.WriteLine(aiU6.ToString());
属性
par.Name == "xiaoli"
以上写成表达树节点式代码如下:
static void Main(string[] args) { ParameterExpression par = Expression.Parameter(typeof(People),"par"); MemberExpression property = Expression.Property(par, "Name"); BinaryExpression binary = Expression.Assign(property, Expression.Constant("xiaoming")); BinaryExpression eqb = Expression.Equal(property,Expression.Constant("xiaoli")); } public class People { public int Age { get; set; } public string Name { get; set; } public int Id; }
扩展
InvocationExpression
说明:Expression.Invoke方法是对lbamda表达式的调用并且传入实参,其实就是labmda表达式树的再次封装。以下是Expression.Invoke方法应用实例
案例一、实现扩展方法
public static Func<T, bool> Or<T>(this Func<T, bool> expr1, Func<T, bool> expr2)
{
return x => expr1(x) || expr2(x);
}
具体代码:
public static Expression<Func<T, bool>> Or<T>( this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var parameter = Expression.Parameter(typeof(T), "x"); var invokedExpr1 = Expression.Invoke(expr1, parameter); var invokedExpr2 = Expression.Invoke(expr2, parameter); return Expression.Lambda<Func<T, bool>>( Expression.OrElse(invokedExpr1, invokedExpr2), parameter); }
案例二、调用表达式树并且传入参数
Expression<Func<int, int, bool>> largeSumTest = (num1, num2) => (num1 + num2) > 1000; InvocationExpression invocationExpression= Expression.Invoke( largeSumTest, Expression.Constant(539), Expression.Constant(281)); Console.WriteLine(invocationExpression.ToString()); // Invoke((num1, num2) => ((num1 + num2) > 1000),539,281)
案例三、
static void Main(string[] args) { List<Person> PersonLists = new List<Person>() { new Person { Name = "张三",Age = 20,Gender = "男", Phones = new List<Phone> { new Phone { Country = "中国", City = "北京", Name = "小米" }, new Phone { Country = "中国",City = "北京",Name = "华为"}, new Phone { Country = "中国",City = "北京",Name = "联想"}, new Phone { Country = "中国",City = "台北",Name = "魅族"}, } }, new Person { Name = "松下",Age = 30,Gender = "男", Phones = new List<Phone> { new Phone { Country = "日本",City = "东京",Name = "索尼"}, new Phone { Country = "日本",City = "大阪",Name = "夏普"}, new Phone { Country = "日本",City = "东京",Name = "松下"}, } }, new Person { Name = "克里斯",Age = 40,Gender = "男", Phones = new List<Phone> { new Phone { Country = "美国",City = "加州",Name = "苹果"}, new Phone { Country = "美国",City = "华盛顿",Name = "三星"}, new Phone { Country = "美国",City = "华盛顿",Name = "HTC"} } } }; Expression<Func<Person, bool>> lambdaone = ex => ex.Name.Equals("张三"); Expression<Func<Person, bool>> lambdatwo = ex => ex.Age == 30; // 创建参数表达式 var ss = lambdatwo.Parameters.Cast<Expression>(); /* Parameters.Cast 是强制转化 将 ReadOnlyCollection<ParameterExpression>转成 IEnumerable<TResult> 表达式树里面再套表达式树*/ InvocationExpression invocation = Expression.Invoke(lambdaone, lambdatwo.Parameters.Cast<Expression>()); // 创建or运算 BinaryExpression binary = Expression.Or(lambdatwo.Body, invocation); // 生成lambda表达式 var exp = Expression.Lambda<Func<Person, bool>>(binary, lambdatwo.Parameters); var Lists = PersonLists.Where(exp.Compile()); foreach (var List in Lists) { Console.WriteLine(List.Name); } Console.Read(); } public class Phone { public string Country { get; set; } public string City { get; set; } public string Name { get; set; } } public class Person { public string Name { get; set; } public string Gender { get; set; } public int Age { get; set; } public List<Phone> Phones { get; set; } }