• Expression Tree 入门


    System.Linq.Expressions 命名空间

    System.Linq.Expressions 命名空间包含一些类、接口和枚举,它们使语言级别的代码表达式能够表示为表达式目录树形式的对象。

    抽象类 Expression 可提供用于对表达式目录树进行建模的类层次结构的根目录。

    Expression 派生的此命名空间中的类(例如 MemberExpressionParameterExpression)用于表示表达式目录树中的节点。Expression 类包含 static(在 Visual Basic 中为 Shared)工厂方法,可创建各种类型的表达式目录树节点。

    枚举类型 ExpressionType (Add, and, Call 等表示表达式的动作类型)指定唯一节点类型。

    常用的类

      BinaryExpression 表示包含二元运算符的表达式。
      ConditionalExpression 表示包含条件运算符的表达式。
      ConstantExpression 表示具有常量值的表达式。
    abstract Expression 提供一种基类,表示表达式树节点的类派生自该基类。它还包含用来创建各种节点类型的 static(在 Visual Basic 中为 Shared)工厂方法
      MemberExpression 表示访问字段或属性。
      MethodCallExpression 表示对静态方法或实例方法的调用。
      NewExpression 表示构造函数调用。
      UnaryExpression 表示包含一元运算符的表达式。
      ParameterExpression 变量, 参数表达式
    3 //常数表达式
    a //变量或参数表达式
    !a //一元逻辑非表达式
    a + b //二元加法表达式
    Math.Sin(a) //方法调用表达式
    new StringBuilder() //new 表达式
    public class MyExpression
        {
            public string _str;
            public int _int;
            public string Name { get; set; }
            public MyExpression() { }
            public MyExpression(string str) {
                _str = str;
            }
            /// <summary>
            /// 创建 a+2+3表达式.
            ///分解动作. (a+2)+3. ==> (变量 二元操作符+ 常量) 二元操作符+ 常量.
            /// </summary>
            /// <returns></returns>
            public static Func<int, int> Expression1()
            {
                ParameterExpression param = System.Linq.Expressions.Expression.Parameter(typeof(System.Int32), "a");
                //这样
                BinaryExpression plus1 = Expression.MakeBinary(ExpressionType.Add, param,
                    Expression.Constant(2));
                BinaryExpression plus2 = Expression.MakeBinary(ExpressionType.Add, plus1,
                    Expression.Constant(3));
                //或者这样
                //ConstantExpression con1 = Expression.Constant(2);
                //ConstantExpression con2 = Expression.Constant(3);
                //BinaryExpression plus1 = Expression.Add(param, con1);
                //BinaryExpression plus2 = Expression.Add(plus1, con2);
                //编译成委托
                Expression<Func<int, int>> lam = Expression.Lambda<Func<int, int>>(plus2, param);
                return lam.Compile(); ;
            }
            public static int ToDouble(int Number) {
                return Number * Number;
            }
            public int ToDouble_Instance(int Number)
            {
                return Number * Number;
            }
            /// <summary>
            /// 调用静态方法MyExpression.ToDouble方法
            /// </summary>
            /// <returns></returns>
            public static Func<int, int> Expression2() {
                //创建参数
                ParameterExpression param = Expression.Parameter(typeof(int),"number");
                //调用方法
                MethodCallExpression method = Expression.Call(typeof(MyExpression).GetMethod("ToDouble"), param);
                return Expression.Lambda<Func<int, int>>(method, param).Compile(); ;
            }
            /// <summary>
            /// 调用动态方法MyExpression.ToDouble方法
            /// </summary>
            /// <returns></returns>
            public static Func<int, int> Expression3()
            {
                //创建参数
                ParameterExpression param = Expression.Parameter(typeof(int), "number");
                //调用方法
                MethodCallExpression method = Expression.Call(typeof(MyExpression).GetMethod("ToDouble_Instance"), param);
                return Expression.Lambda<Func<int, int>>(method, param).Compile(); ;
            }
            /// <summary>
            /// 实例化
            /// </summary>
            /// <returns></returns>
            public static Func<string,T> CreateInstance<T>() where T: class {
                //创建参数
                ParameterExpression param = Expression.Parameter(typeof(string), "str");
                //调用方法
                var exp = Expression.New(typeof(T).GetConstructor(new Type[] { typeof(string) }), param);
                return Expression.Lambda<Func<string, T>>(exp, param).Compile();
            }
            /// <summary>
            /// 创建new int[] { a, b, a + b}数组
            /// </summary>
            /// <returns></returns>
            public static Func<int, int, int[]> createIntArray()
            {
                ParameterExpression a = Expression.Parameter(typeof(int), "a");
                ParameterExpression b = Expression.Parameter(typeof(int), "b");
                BinaryExpression aPlusb = Expression.MakeBinary(ExpressionType.Add, a, b);
                var exp = Expression.NewArrayInit(typeof(int), a, b, aPlusb);
     
                ParameterExpression[] parm = { a,b};
                return Expression.Lambda<Func<int, int, int[]>>(exp, parm).Compile();
            }
            /// <summary>
            /// a.Length>3 | b>0
            /// </summary>
            /// <returns></returns>
            public static Func<string, int, bool> createBool() {
                ParameterExpression a = Expression.Parameter(typeof(string), "a");
                var property = Expression.PropertyOrField(a, "Length");
                var exp1 = Expression.MakeBinary(ExpressionType.GreaterThan, property, Expression.Constant(3));
                
                ParameterExpression b = Expression.Parameter(typeof(int), "b");
                var exp2 = Expression.MakeBinary(ExpressionType.GreaterThan, b, Expression.Constant(0));
     
                var or = Expression.MakeBinary(ExpressionType.Or, exp1, exp2);
     
                return Expression.Lambda<Func<string, int, bool>>(or,a,b).Compile();
            }
     
            public static IQueryable<T> Order<T>(IQueryable<T> query, string field)
            {
                ParameterExpression x = Expression.Parameter(typeof(T), "x");
                var property = Expression.Property(x, field);
     
                PropertyInfo pi = typeof(T).GetProperty(field);
                Type[] types = new Type[2];
                types[0] = typeof(T);
                types[1] = pi.PropertyType;
                var lambda = Expression.Lambda(property, x);
                var exp = query.AsQueryable().Expression;
                MethodCallExpression call = Expression.Call(typeof(Queryable), "OrderBy", types,exp, lambda);
                return query.AsQueryable().Provider.CreateQuery<T>(call);
                
            }
            /// <summary>
            /// 实例化2
            /// </summary>
            /// <returns></returns>
            public static Func<object> CreateInstance(string classpath)
            {
                //调用方法
                var exp = Expression.New(Type.GetType(classpath).GetConstructor(Type.EmptyTypes));
                return Expression.Lambda<Func<object>>(exp).Compile();
            }
        }
    特别需要注意的是, linq动态查询, 最后call方法, 需要加上原有的表达式, 这个暂时不理解
    static void Main(string[] args)
            {
                Expression<Func<int, int, int>> expression = (a, b) => a + b;
     
                var per=MyExpression.Expression2();
                Console.WriteLine("调用静态方法:" + per(5));
                Console.WriteLine("调用动态方法:" + MyExpression.Expression2()(10));
     
                MyExpression exp = MyExpression.CreateInstance<MyExpression>()("jianjialin");
                Console.WriteLine("创建对象:" + exp._str + "     " + MyExpression.CreateInstance<MyExpression>().ToString());
     
                Console.WriteLine("创建数组:" + MyExpression.createIntArray()(2,3)[2]);
     
                Console.WriteLine("a.Length>3 | b>0的表达式"+MyExpression.createBool()("abcd",-2));
     
                IList<Student> lst = new List<Student> { 
                    new Student{ Name="刘备",Age=40},
                    new Student{ Name="张飞",Age=20},
                    new Student{ Name="关羽",Age=30}
                    
                };
                Console.ReadKey();
            }
  • 相关阅读:
    ubuntu 修改mysql 5.7数据库密码
    maven 配置
    数据仓库的命名规范
    mysql 之 在查询字段中得出分钟数
    mysql 之 timestampdiff() 函数 ,得到间隔分钟数
    linux 服务器上下载文件到本地
    mysql 之 时间格式 今年的第一天,去年的第一天
    mysql 之 str_to_date ()函数 和date_format()函数
    网络不可用时~更改DNS并刷新
    mysql之 round()函数 , concat()函数
  • 原文地址:https://www.cnblogs.com/jianjialin/p/2099874.html
Copyright © 2020-2023  润新知