• C#之Expression表达式目录树


    一、Expression是什么

    1、和委托的区别

    a、委托是编译时,表达式目录树是运行时,在应用程序运行过程中可以重新赋值

    b、委托相当于是拿到别人dll文件,只能调用里面的方法;表达式目录树相当于拿到了别人的源码,可以进行扩展

    2、Expression本质

    a、表达式目录树是一个类的封装,描述了一个结构,有身体部分和参数部分

    b、表达式目录树展开后的每一个节点也是一个表达式目录树

    二、Expression动态拼接

    1、最基础版本

    Expression<Func<int>> expression = () => 123 + 456;
    
    ConstantExpression constant1= Expression.Constant(123,typeof(int));
    ConstantExpression constant2 = Expression.Constant(456, typeof(int));
    BinaryExpression binaryExpression =Expression.Add(constant1, constant2);
    Expression<Func<int>> expressionReslut = Expression.Lambda<Func<int>>(binaryExpression,Array.Empty<ParameterExpression>());
    
    Func<int> func = expressionReslut.Compile();
    var result = func.Invoke();

    2、带参数版本

    Expression<Func<int,int>> expression = m => m + 123;
    
    ParameterExpression parameterExpression =Expression.Parameter(typeof(int),"m");
    ConstantExpression constantExpression = Expression.Constant(123, typeof(int));
    BinaryExpression binaryExpression =Expression.Add(parameterExpression, constantExpression);
    Expression<Func<int,int>> expressionReslut = Expression.Lambda<Func<int,int>>(binaryExpression, new ParameterExpression[1] 
    
    parameterExpression
    });
    
    Func<int,int> func = expressionReslut.Compile();
    var result = func.Invoke(10);

    3、带有多个参数

    Expression<Func<int, int, int>> expression = (m, n) => m * n + 2;
    
    ParameterExpression parameterExpressionM = Expression.Parameter(typeof(int), "m");
    ParameterExpression parameterExpressionN = Expression.Parameter(typeof(int), "n");
    BinaryExpression multiply = Expression.Multiply(parameterExpressionM, parameterExpressionN);
    ConstantExpression constantExpression = Expression.Constant(2);
    BinaryExpression plus = Expression.Add(multiply, constantExpression);
    Expression<Func<int, int, int>> expression1 = Expression.Lambda<Func<int, int, int>>(plus, new ParameterExpression[2
    {
      parameterExpressionM,
      parameterExpressionN
    });
    Func<int, int, int> func1 = expression1.Compile();
    int iResult1 = func1.Invoke(20, 30);

    4、对象字段值比较

    如果碰到很长的表达式目录树,建议先拼装右边,再拼装左边

    Expression<Func<User, bool>> expression = (x) => x.Id.ToString() == "1" && x.Name.Equals("xiaohemiao");
    
    // 1、声明参数
    ParameterExpression parameterExpression=Expression.Parameter(typeof(User),"x");
    // 2、因为要拼装x.Name,所以要先找到Name
    PropertyInfo propName = typeof(User).GetProperty("Name");
    // 3、拼装x.Name
    MemberExpression memberExpression = Expression.Property(parameterExpression, propName);
    // 4、因为需要调用Equals,所以要先获取Equals方法
    MethodInfo methodInfo= typeof(string).GetMethod("Equals",new Type[] { typeof(string)});
    // 5、调用Equals方法,x.Name.Equals("xiaohemiao") ,调用需要“xiaohemiao”,所以先声明一个字符串常量
    ConstantExpression constantExpressionRight =Expression.Constant("xiaohemiao", typeof(string));
    // 6、拼装x.Name.Equals("xiaohemiao")
    MethodCallExpression MethodCallExpressionRight=Expression.Call(memberExpression, methodInfo, constantExpressionRight);
    // 7、开始拼装左边 拼装x.Id,所以先找到Id
    PropertyInfo propId = typeof(User).GetProperty("Id");
    // 8、拼装x.Id
    MemberExpression memberExpressionId = Expression.Property(parameterExpression, propId);
    // 9、因为要拼装x.Id.ToString(),所以先找到ToString方法
    MethodInfo toString = typeof(int).GetMethod("ToString", new Type[0] { });
    // 10、开始拼装x.Id.ToString()
    MethodCallExpression methodCallExpressionLeft1=Expression.Call(memberExpressionId, toString, Array.Empty<Expression>());
    // 11、需要声明一个常量
    ConstantExpression constantExpressionLeft= Expression.Constant("1",typeof(string));
    // 12、拼装x.Id.ToString().Equals("1"),需要调用Equals方法,先获取Equals方法--上面已经获取过,可以直接使用
    BinaryExpression BinaryExpression = Expression.Equal(methodCallExpressionLeft1,  constantExpressionLeft);
    // 13、左边和右边都拼装好了,现在要把左边和右边 && 起来
    BinaryExpression binaryExpression=Expression.AndAlso(BinaryExpression, MethodCallExpressionRight);
    
    Expression<Func<User, bool>> expression1 = Expression.Lambda<Func<User, bool>>(binaryExpression, new ParameterExpression[1]
    {
     parameterExpression
    });
    
    Func<User, bool> func = expression1.Compile();
    var result = func.Invoke(new User() { 
     Id=1,
     Name="xiaohemiao"
    });
  • 相关阅读:
    Swift的函数与函数指针、闭包Closure等相关内容介绍
    spring+dubbo整合
    常用设计模式-适配器模式
    常用设计模式-工厂模式
    java动态代理
    程序对关系型数据库批量操作
    springboot整合mybatis
    JAVA代码实现多级树结构封装对象
    springboot集成redis缓存
    springboot入门
  • 原文地址:https://www.cnblogs.com/sportsky/p/16006713.html
Copyright © 2020-2023  润新知