Expressions-表达式树进阶应用(动态查询、动态执行)

前言

通过上篇我们大概了解了下表达式树大概是什么,那本篇将带来表达式树的一些进阶应用。

动态构建表达式树

在实际应用中无论是用于查询还是其他方面我们或多或少都会想能不能动态表达式树来降低开发时间。比如如果查询时用拼写SQL形式查询,我们可以写一个SQL拼接的方法,这个方法通过字符串拼接外部传入的 “WHERE”就能比较灵活的写出一个通用查询方法。而此时如果换成通过写表达式树的形式的话我们能不能类似于以前的哪种字符串拼接的方式拼接出一个我们想要的表达式树呢?答案时能的。表达式树在程序运行时其就是一个表达式树对象,我们只需要参照MSDN中的文档就能创建出任意我们想要的表达式树对象,只是这可能会比较麻烦。
那么这里我们可以选择自己花时间自己好好研究下表达式树,也可以用现有的第三方工具(库)比如DynamicExpresso。

动态创建委托

依旧直接上代码

  /// 
    /// 账号金额
    /// 
    public class AccountAmount
    {
        public int Id { get; set; }
        /// 
        /// 冻结金额
        /// 
        public int Frozen { get; set; }
        /// 
        /// 可用金额
        /// 
        public int Available { get; set; }

        /// 
        /// 计算总额
        /// 
        /// 
        public int ComputeAllAmount ()
        {
            return Frozen + Available;
        }
    }

    internal class Program
    {
        private static void Main (string [ ] args)
        {
            AccountAmount accountAmount=new AccountAmount()
            {
                Id=0,
                Frozen=50,
                Available=100
            };

            Interpreter target = new Interpreter();//创建 解释器

            Func getForzenFunc = target.ParseAsDelegate>("accountAmount.Frozen" , "accountAmount");//创建一个获取冻结金额的Func
            Console.WriteLine("获取冻结金额:" + getForzenFunc(accountAmount));

            Func callComputeAllAmountFunc = target.ParseAsDelegate>("accountAmount.ComputeAllAmount()" , "accountAmount");//创建一个调用计算总额方法的Func
            Console.WriteLine("调用计算总额方法:" + callComputeAllAmountFunc(accountAmount));

            Func computeAllAmountFunc = target.ParseAsDelegate>("accountAmount.Frozen+accountAmount.Available" , "accountAmount");//创建一个计算总额的Func
            Console.WriteLine("计算总额:" + computeAllAmountFunc(accountAmount));

            Console.ReadKey();
        }

    }

执行结果:
在这里插入图片描述

从上可以看出,我们可以通过组装表达式树动态的生成委托,并通过调用委托完成对应的操作。

动态创建Linq查询表达式树

 /// 
    /// 账号金额
    /// 
    public class AccountAmount
    {
        public int Id { get; set; }
        /// 
        /// 冻结金额
        /// 
        public int Frozen { get; set; }
        /// 
        /// 可用金额
        /// 
        public int Available { get; set; }

        public override string ToString ()
        {
            return string.Format("ID:{0},Frozen:{1},Available:{2}" , Id , Frozen , Available);
        }
    }

    internal class Program
    {
        private static void Main (string [ ] args)
        {
            List accountAmountList =new List();
            accountAmountList.Add(new AccountAmount()
            {
                 Id=1,
                 Frozen=50,
                 Available=100,
            });
            accountAmountList.Add(new AccountAmount()
            {
                Id = 2 ,
                Frozen = 20 ,
                Available = 200 ,
            });
            accountAmountList.Add(new AccountAmount()
            {
                Id = 3 ,
                Frozen = 70 ,
                Available = 50 ,
            });
            
            Interpreter target = new Interpreter();//创建 解释器

            Func whereFunc = target.ParseAsDelegate>("accountAmount.Frozen <50" , "accountAmount");//创建一个冻结金额小于50的Func
            Console.WriteLine("冻结金额小于50的账号:"  );
            var data1= accountAmountList.Where(whereFunc);
            foreach (var a in data1 )
            {
                Console.WriteLine(a.ToString());
            }

            System.Linq.Expressions.Expression> whereExpression=target.ParseAsExpression>("accountAmount.Frozen >50" , "accountAmount");//创建一个冻结金额大于50的表达式树
           var data2= accountAmountList
                .AsQueryable()//模拟使用EF查询
                .Where(whereExpression)
                .ToList();
            Console.WriteLine("冻结金额大于50的账号:");
            foreach ( var a in data2 )
            {
                Console.WriteLine(a.ToString());
            }
            Console.ReadKey();
        }

    }

执行结果
在这里插入图片描述
这里直接传递了字符串,通过字符串去解析创建了委托和表达式树。实际应用中可以根据实际情况来拼接这个字符串。

你可能感兴趣的:(Expressions-表达式树进阶应用(动态查询、动态执行))