基于Linq表达式做的一个简单的表达式生成器

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Linq.Expressions;

namespace Model
{
    [NotMapped]
    public class FilterInfo
    {
        /// <summary>
        /// 字段名称
        /// </summary>
        public string FieldName { get; set; }
        /// <summary>
        /// 字段值
        /// </summary>
        public object FieldValue { get; set; }
        /// <summary>
        /// 操作符
        /// </summary>
        public FilterOperator Operator { get; set; }
        /// <summary>
        /// 构建表达式
        /// </summary>
        /// <returns></returns>
        public Func<T, bool> BuildExpression<T>()
        {
            var constEexp = Expression.Constant(FieldValue, this.FieldValue.GetType());
            var paramExp = Expression.Parameter(typeof(T), "x");
            Expression expLeft = null;
            var tp = typeof(T);
            //基元类型直接去paramExp,自定义类型取PropExp
            if (!tp.IsPrimitive && tp != typeof(string))
            {
                expLeft = (Expression)Expression.Property(paramExp, FieldName);
            }
            else
            {
                expLeft = paramExp;
            }
            Expression bExp = null;
            switch (Operator)
            {
                case FilterOperator.GreaterThan://>
                    bExp = Expression.GreaterThan(expLeft, constEexp);
                    break;
                case FilterOperator.GreaterThanOrEqual://>=
                    bExp = Expression.GreaterThanOrEqual(expLeft, constEexp);
                    break;
                case FilterOperator.LessThan://<
                    bExp = Expression.LessThan(expLeft, constEexp);
                    break;
                case FilterOperator.LessThanOrEqul://<=
                    bExp = Expression.LessThanOrEqual(expLeft, constEexp);
                    break;
                case FilterOperator.OrElse://!=
                    bExp = Expression.NotEqual(expLeft, constEexp);
                    break;
                case FilterOperator.Like:
                    if (this.FieldValue.GetType() != typeof(string))
                    {
                        throw (new Exception("Like只能用于string类型的字段操作"));
                    }
                    bExp = Expression.Call(typeof(FilterInfo).GetMethod("Contains", new Type[] { typeof(string), typeof(string) }), expLeft, constEexp);
                    break;
                default://=
                    bExp = Expression.Equal(expLeft, constEexp);
                    break;
            }
            var exp = Expression.Lambda<Func<T, bool>>(bExp, paramExp);
            Console.WriteLine(exp);
            return exp.Compile();
        }
        /// <summary>
        /// 用该静态方法实现like
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool Contains(string a, string b)
        {
            if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b))
            {
                return false;
            }
            return a.Contains(b);
        }
    }
    /// <summary>
    /// 操作符枚举
    /// </summary>
    public enum FilterOperator
    {
        /// <summary>
        /// >
        /// </summary>
        GreaterThan,
        /// <summary>
        /// =
        /// </summary>
        Equal,
        /// <summary>
        /// <
        /// </summary>
        LessThan,
        /// <summary>
        /// <=
        /// </summary>
        LessThanOrEqul,
        /// <summary>
        /// >=
        /// </summary>
        GreaterThanOrEqual,
        /// <summary>
        /// !=
        /// </summary>
        OrElse,
        /// <summary>
        /// contain
        /// </summary>
        Like
    }
}

使用该表达式生成器,可以生成简单的匿名查询函数来过滤查询结果。如果我们在项目中用了EF框架,就可以在业务层中通过这个类来构建查询条件然后传到DAL层来执行,使用方法如下:

 //整形数组查询
            int[] nums = { 5, 4, 2, 2, 9, 8, 6, 7, 2, 0 };
            FilterInfo filterInt = new FilterInfo() { FieldName = "x", FieldValue = 2, Operator = FilterOperator.LessThanOrEqul };
            var intFunc = filterInt.BuildExpression<int>();
            var r = nums.Where(intFunc);
            foreach (var i in r)
            {
                Console.WriteLine(i);
            }
            Console.WriteLine("int array search complete");
            //字符串数组查询
            string[] strArray = { "string1", "string11", "string2", "string2134", "stringOld" };
            FilterInfo f = new FilterInfo() { FieldName = "x", FieldValue = "1", Operator = FilterOperator.Like };
            var fc = f.BuildExpression<string>();
            strArray.Where(fc).ToList().ForEach(s => Console.WriteLine(s));
            //对象列表查询
            List<Org> orglist = new List<Org>();
            orglist.Add(new Org() { Guid = Guid.NewGuid().ToString(), Name = "spring" });
            for (int i = 0; i < 10; i++)
            {
                orglist.Add(new Org() { Guid = Guid.NewGuid().ToString(), Name = "orgName" + Guid.NewGuid().ToString() });
            }
            FilterInfo filter = new FilterInfo() { FieldName = "Name", FieldValue = "Name", Operator = FilterOperator.Like };
            var func = filter.BuildExpression<Org>();
            var orgSearchList = orglist.Where(func);
            foreach (var o in orgSearchList)
            {
                Console.WriteLine(o.Name);
            }
            Console.WriteLine("org list search Complete");
时间: 2024-09-30 06:17:21

基于Linq表达式做的一个简单的表达式生成器的相关文章

【龙书笔记】用Python实现一个简单数学表达式从中缀到后缀语法的翻译器(采用递归下降分析法)

上篇笔记介绍了语法分析相关的一些基础概念,本篇笔记根据龙书第2.5节的内容实现一个针对简单表达式的后缀式语法翻译器Demo. 备注:原书中的demo是java实例,我给出的将是逻辑一致的Python版本的实现. 在简单后缀翻译器代码实现之前,还需要介绍几个基本概念. 1. 自顶向下分析法(top-down parsing) 顾名思义,top-down分析法的思路是推导产生式时,以产生式开始符号作为root节点,从上至下依次构建其子节点,最终构造出语法分析树.在具体实现时,它会把输入字符串从左到右

利用KBEngine +U3D 做的一个简单MMO手游Demo

利用KBE +U3D 做的一个简单MMO手游Demo目前只完成到一个普通攻击和一个火球术,  火球术需要点击怪物后才能释放.点击npc后会跳到一个副本.里面有一只半兽人. 欢迎大家来试玩 并提出宝贵意见.http://pan.baidu.com/s/1dDtVjnb 感谢kbe 一直以来的帮助.

[Ruby on Rails系列]6、一个简单的暗语生成器与解释器(上)

[0]Ruby on Rails 系列回顾 [Ruby on Rails系列]1.开发环境准备:Vmware和Linux的安装 [Ruby on Rails系列]2.开发环境准备:Ruby on Rails开发环境配置 [Ruby on Rails系列]3.初试Rails:使用Rails开发第一个Web程序 [Ruby on Rails系列]4.专题:Rails应用的国际化[i18n] [Ruby on Rails系列]5.专题:Talk About SaSS [1]任务目标 本次主要是要实现一

基于Spring aop写的一个简单的耗时监控

前言:毕业后应该有一两年没有好好的更新博客了,回头看看自己这一年,似乎少了太多的沉淀了.让自己做一个爱分享的人,好的知识点拿出来和大家一起分享,一起学习. 背景: 在做项目的时候,大家肯定都遇到对一些对方法,模块耗时的监控,为了方便性能的监控,问题的定位等.如果每一个方法里都加上 ... Stopwatch watch = Stopwatch.createStarted(); ... watch.elapsed(TimeUnit.MILLISECONDS) ... 类似的代码肯定没问题,但是就会

基于gin框架搭建的一个简单的web服务

刚把go编程基础知识学习完了,学习的时间很短,可能还有的没有完全吸收.不过还是在项目中发现知识,然后在去回顾已学的知识,现在利用gin这个web框架做一个简单的CRUD操作. 1.Go Web框架的技术选型 Top 6 web frameworks for Go as of 2017,可以看看这个go语言中Web框架的对比和老大的推荐,我选择gin框架作为学习go语言的框架. image.png 2.Gin介绍 gin框架的中文文档,这个文档相当好,清晰明了解释gin框架的整个用法.下面是gin

一个简单的ruby生成器例子(用连续体Continuation实现)

ruby中有很多经典的驱动器结构,比如枚举器和生成器等.这次简单介绍下生成器的概念.生成器是按照功能要求,一次产生一个对象,或称之为生成一个对象的方法.ruby中的连续体正好可以用来完成生成器的功能.连续体说起来晦涩,其实还是很简单的,它有3个特点: 1. callcc方法会给代码块传一个连续体对象,你可以保存该对象; 2. 当调用连续体的call方法时指令流会跳转到callcc方法之后; 3. 如果给连续体的call方法传递对象,则callcc方法会返回该对象,如果不传递对象,callcc会返

6. Swift 基于Xmpp和openfire实现一个简单的登录注册

1. 基本步骤:首先导入Xmpp框架,配置环境 ->由于我们使用的是OC的Xmpp框架,再进行Swift开发时需要进行桥接. 具体方法就是创建一个基于c的.h的头文件,然后将我们需要编译OC的语言的头文件包含这个.h文件中: ->然后导入如下库文件,在头头文件选择路径中 如上图, 设置header Search paths 设置头文件的搜索路径,导入libxml2库文件相对路径,***注意前面是 usr .以前第一次装的时候写成user找了半个多小时 -> 然后创建界面,随便弄两个框框和

用ios做的一个简单的记事本

#import "ViewController.h" @interface ViewController ()@property (weak, nonatomic) IBOutlet UITextField *标题;  //用的是一个text按键 @property (weak, nonatomic) IBOutlet UITextView *文本;  //用的是一个text view按键 @end @implementation ViewController- (IBAction)创

今天做了一个简单的PHP网页

index.php <html> <head>     <title>First PHP</title> </head> <body> <form name="form_a" method="post", action="fa.php">     用户名:     <input name="user" type="text&qu