【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; }

        }

 

posted @ 2021-10-20 12:28  小林野夫  阅读(351)  评论(0)    收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/