zoukankan      html  css  js  c++  java
  • 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();
            }
  • 相关阅读:
    树的子结构(剑指offer_26)
    合并两个排序的链表(剑指offer_25)
    反转链表(剑指offer_24)多看多思多想
    链表中环的入口结点(剑指offer_23)
    链表中倒数第k个节点
    调整数组顺序使奇数位于偶数前面(剑指offer_21)
    表示数值的字符串(剑指offer_20)
    1676. 跳石头
    1670. 回合制游戏
    1667. 区间统计(回顾)
  • 原文地址:https://www.cnblogs.com/jianjialin/p/2099874.html
Copyright © 2011-2022 走看看