基于Expression Lambda表达式树的通用复杂动态查询构建器——《构思篇二》已开源

接续[上篇之预告]

本篇来讲讲,如何根据前面设计的查询描述器构造出可执行的表达式。正如标题所示,实现手段将采用Expression Lambda技术。

先来看看主角System.Linq.Expressions.Expression 长什么样,都有些什么东西,能做什么。 先看看它的类图:

 

  • System.Linq.Expressions.ConstantExpression 常量

  • System.Linq.Expressions.DefaultExpression 默认值

  • System.Linq.Expressions.IndexExpression 索引

  • System.Linq.Expressions.MemberExpression 成员(属性或字段)

  • System.Linq.Expressions.MethodCallExpression 方法调用

  • System.Linq.Expressions.ParameterExpression 参数

  • System.Linq.Expressions.UnaryExpression 一元运算

  • System.Linq.Expressions.BinaryExpression 二元运算

  • System.Linq.Expressions.LambdaExpression 委托

 

我们主要使用Expression这个类,它包含各种节点类型的 static工厂方法。特别是以下这些方法,对应了查询需要用到的逻辑、比较、数学,等各种运算操作。

逻辑运算  
AndAlso(Expression, Expression) 表示And逻辑运算
OrElse(Expression, Expression) 表示Or逻辑运算
比较运算  
LessThan(Expression, Expression) 表示小于:"<"
LessThanOrEqual(Expression, Expression) 表示大于等于:“<="
GreaterThan(Expression, Expression) 表示大于:”>“
GreaterThanOrEqual(Expression, Expression) 表示大等于:”>="
Equal(Expression, Expression) 表示等于:”=“
NotEqual(Expression, Expression) 表示不等于:”!="
IsTrue(Expression) 测试表达式结果是否为“True"
IsFalse(Expression) 测试表达式结果是否为“False"
Not(Expression) 表示”Not"
数学运算  
Add(Expression, Expression) 加法
Subtract(Expression, Expression) 减法
Multiply(Expression, Expression) 乘法
Divide(Expression, Expression) 除法
Modulo(Expression, Expression) 模除
Power(Expression, Expression) 幂运算
一些操作  
Parameter(Type) 包装一个类型为Type的参数
Call(Expression, MethodInfo, Expression, Expression) 包装一个方法调用
Bind(MemberInfo, Expression) 包装一个成员绑定,(属性或字段)
Quote(Expression) 包装一个括号
MakeUnary(ExpressionType, Expression, Type) 包装一个一元运算
MakeBinary(ExpressionType, Expression, Expression) 包装一个二元运算
TypeAs(Expression, Type) 包装一个显式引用或装箱转换,其中如果转换失败则提供“null”。
Coalesce(Expression, Expression, LambdaExpression) 包装表示给定转换函数的聚结操作。
变量、常量、字段、属性  
Default(Type) 包装一个指定类型的默认值
Constant(Object, Type) 包装一个常量
Assign(Expression, Expression) 赋值操作
Variable(Type, String) 包装一个变量定义
Property(Expression, MethodInfo) 包装一个属性
Field(Expression, FieldInfo) 包装一个字段
PropertyOrField(Expression, String) 包装一个指定名称的字段或属性
要的就是这结果  
Lambda(Expression, ParameterExpression[]) 包装一个委托,带有一个参数表达式数组。

以上仅列出了一部分,它涵盖了全部可能要使用到的函数,语句,欲详细了解可以直接乘坐火箭到微软官方网站查看。

这此函数或功能是有了,如何使用呢?来看个例子:将SQL:Table1.A > 5 and Table1.B=3,转成(Table1)=>Table1.A > 5 && Table1.B==3;

Expression的世界里一切都是Expression。因此首先要将Table1A5B3先包装成Expression

  • 开干之前先谈个对象
//实体类:
    public class Table
    {
        public int A;
        public int B;
    }

 

  • 然后包装各种Expression
​
    //将Table1包装成ParameterExpression:
    var p=Expression.Parameter(typeof(Table1),"Table1");
​
    //将5、3这两个常量包装成ConstantExpression:
    var num5=Expression.Constant(5,typeof(int));
    var num3=Expression.Constant(3,typeof(int));
​
    //将两个属性包装成MemberExpression。
    var a=Expression.PropertyOrField(p,"A")
    var b=Expression.PropertyOrField(p,"B")
​
    //构造Table1.A>5:
    var gt=Expression.GreaterThen(a,num5); 
    //构造Table1.A=3:
    var eq=Expression.Equal(b,num3);    
    
​

 

  • 再构造两个比较式
   //构造Table1.A>5:
   var gt=Expression.GreaterThen(a,num5); 
    //构造Table1.A=3:
    var eq=Expression.Equal(b,num3);    

 

  •  加上逻辑And将两个比较式连接起来
    //构造Table1.A>5 && Table1.A=3
    var exp=Expression.AndAlso(gt,eq);

 

  •  结果就要出来了
//结果就获得了:
    var lambda=Expression.Lambda()
        

 

  • 来来来,测试一下康康接果:
    /*===============来来来,测试一下:===============*/    
    var f=lambda.Compile();
    var x=f.DynamicInvoke(new Table(){A=6,B=3});
    var y = f.DynamicInvoke(new Table() { A = 2, B = 3 });
    Console.WriteLine("x:{0}\ny:{1}",x,y);
    Console.WriteLine("Lambda:{0}",lambda.ToString());          
    /*输出:
    结果对吗?我也不知道,我撸得这么辛苦,先让电脑休息一下,各位看官只要Ctrl+C,Ctrl+V就可以看到了.
    */

 

  • OK,其它各种操作,只要依葫芦画瓢便大功可成! 先爽一下!
  • 好,暂且爽到这里,欲看如何把括号弄成俄罗斯套娃,且看下回分解.
  • 随手点个赞,让我也爽爽,可好!

本文转载于网络 如有侵权请联系删除

相关文章

  • PriorityQueue 源码分析[通俗易懂]

    大家好,又见面了,我是你们的朋友全栈君。学过数据结构的人应该对Queue队列很熟悉了,队列是一种先进先出(FIFO)的数据结构,所以它出队列的优先级就是进入队列的次序。但我们有时候需要其它的优先级,很多高级语言都会提供带优先级的队列,在Java中就是PriorityQueue了,今天我们来看下PriorityQueue的使用和实现。使用PriorityQueue的使用很简单,如下。publicstaticvoidmain(String[]args){ PriorityQueue<Integer>priorityQueue=newPriorityQueue<>(); priorityQueue.add(1); priorityQueue.add(2); priorityQueue.add(3); System.out.println(priorityQueue.poll()); }复制如果Queue中元素是整数,其优先级是最小最优先,其它类型或者其它优先级需要传入自定义comparator。下面代码我把优先级定义为最大优先。publicstaticvoidmai

  • 非递归方式进行归并排序链表

    题目来源:LeetCode148题目大意给你一个链表,在O(nlogn)时间复杂度和常数级空间复杂度下,对链表进行排序。啥?把链表排序,把时间复杂度控制在O(nlogn)?,链表不像数组,排序没有那么方便啊!归并排序,常数级空间复杂度?那只能非递归实现了~~不过我不知道该怎么写,看了评论区,自己整理了一下。算法实现ListNodemergetSort(ListNodehead){ if(head==null||head.next==null)returnhead; intlistLength=0; for(ListNodel=head;l!=null;l=l.next)listLength++; ListNodehelperRoot=newListNode(0); helperRoot.next=head; ListNodehelper=helperRoot; //步长,即每个子区间的长度 intstep=1; while(step<listLength){ helper=helperRoot; for(ListNodestart=helperRoot.next;start!=n

  • ROS学习记录②:Topic通讯和代码练习

    Topic通讯和代码练习四、Topic通讯4.1Publisher创建4.2Publisher调试4.2.1rostopic工具(命令行)4.2.2rqt_topic工具(可视化)4.3Subscriber创建4.4Subscriber调试4.4.1publisher(程序)4.4.2rostopic工具(命令行)4.4.3rqt_topic工具(可视化)4.5Topic命令行工具五、Topic通讯练习5.1小乌龟节点启动5.2节点信息查看5.2.1查看小乌龟节点5.2.2可视化工具查询5.3调试工具调试小乌龟5.3.1.rqt_publisher模拟数据发送5.3.2通过命令行模拟数据发送5.4小乌龟案例(代码练习)5.4.1turtle_ctrl.py5.4.2windows.py5.5控制板驱动5.5.1与下位机通讯5.5.2电机主题订阅5.5.3编码器功能实现四、Topic通讯Node间进行通讯,其中发送消息的一方,ROS将其定义为Publisher(发布者),将接收消息的一方定义为Subscriber(订阅者)。考虑到消息需要广泛传播,ROS没有将其设计为点对点的单一传递,而

  • Java Collection类型的forEach方法

    countryList是一个List接口,扩展自Collection:后者又扩展自Iteratable,forEach就是Iterable提供的方法。forEach接受的方法参数为Consumer<?superT>action):Consumer暗示了该操作会造成sideeffect:Consumer是一个FunctionalInterface:/* *Copyright(c)2012,2015,Oracleand/oritsaffiliates.Allrightsreserved. *DONOTALTERORREMOVECOPYRIGHTNOTICESORTHISFILEHEADER. * *Thiscodeisfreesoftware;youcanredistributeitand/ormodifyit *underthetermsoftheGNUGeneralPublicLicenseversion2only,as *publishedbytheFreeSoftwareFoundation.Oracledesignatesthis *particularfileass

  • 4-ESP8266 SDK开发基础入门篇--串口

    https://www.cnblogs.com/yangfengwu/p/11073055.html所有的源码https://gitee.com/yang456/Learn8266SDKDevelop.git手头有任何8266的板子就可以,不需要购买https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-18540610442.2.4297d36cprrnVx&id=569295486025这一节说一下8266的串口说串口之前,先看一下环形队列https://www.cnblogs.com/yangfengwu/p/6822984.html  一会录制一个环形队列的视频其实8266的单片机内部的串口接收有个128字节硬件环形队列单片机接收数据的时候会把数据存到环形队列里面,然后咱就是从环形队列里面取数据...当然,它还有128字节的发送硬件环形队列硬件就是说是纯硬件实现的虽然发送环形队列FIFO有128字节,但是不可以用第128字节哈因为如果用了128字节就会进入另一个中断 应该叫发送溢出中断这个名字是参考接收命名的....

  • hadoop|计算框架从MapReduce1.0到Yarn

    01—HDFS前面介绍了hadoop的分布式存储框架(HDFS),这个框架解决了大数据存储的问题,这是第一步。知道海量数据如何存储后,脚步不能停留,下一步要设计一个框架,用来玩(计算)这些数据时,资源(计算机集群)该如何调度,比如已知1PB的数据存储在了集群(1000台电脑组成)中的10台计算机(DataNode)中,现在要对这些数据进行Map和Reduce计算,该如何做呢? 在理解以下知识前,需要理解一些知识点。任何应用,比如打开一个word文档,打开QQ,都会占用一定的系统资源(CPU,内存,网络资源等),也就是应用要想正常运行就必须分配给它一定的资源,是谁负责分配给QQ软件资源的,一般都是操作系统内核中的资源调度器。02—MapReduce1.0计算框架通俗地讲,首先找到HDFS中的NameNode,因为这个节点可以提供我们1PB的数据都分布存储在哪些计算机中,找到后,直接去这些计算机上进行map和reduce计算就行了。知道这个基本目标后,理解MapReduce的计算框架就会很简单,因为分布式框架的基本思想一般是Master-Slave模式,所以它也不例外,拿出一个进程作为Ma

  • 纳德拉带领微软向云服务营收模式转型

    印度裔高管纳德拉,担任微软新CEO,这已经给微软带来了一股新气象。据印度媒体报道,微软计划针对部分廉价WP手机,免收WP操作系统授权费,分析师表示,如果印度的试验获得成功,微软将会推广到更多的地区,微软正在从依赖销售操作系统赚钱,转型到云服务的营收模式。 众所周知的是,在鲍尔默时代,微软依旧执行的是靠销售“光盘软件”牟利的模式,盖茨留下的Windows和Office两大软件,其收入被鲍尔默做到了最大化。然而在移动互联网的新时代,谷歌和苹果引入了全新的商业模式,硬件操作系统作为基础设施,免费提供给消费者,然后依靠互联网应用、数字内容等“细水长流”的内容,实现长期性的收入。 纳德拉已经意识到,微软传统的一次性销售软件光盘的模式,已经落后于潮流。 据印度媒体报道,微软高层最近和印度的廉价手机制造商进行了协商,微软答应免费提供WP操作系统,以便让手机厂商推出价格十分低廉的WP手机,从而和谷歌安卓手机争抢市场。 面对媒体的采访要求,微软方面表示,无法披露印度商业协议的内容。 Technalysis研究公司的分析师奥德奈尔(Bob-O'Donnell)表示,这是微软进行的一次操作系统免

  • Windows PowerShell 2.0十大新特性

     新的cmdlet、操作符和变量,再加上诸如脚本调试以及后台任务这样的新功能,PowerShell2.0将帮助你开启PowerShell脚本编程的新世界。    如果你希望发挥PowerShell脚本编程的强大功能,但是又发现学习它的难度很大的话,那么PowerShell2.0或许就是你开始上手的最好选择。计划于2009年下半年发布的PowerShell2.0为PowerShell的语言和开发体验加入了许多重要的新特性,让它变得更易于使用,同时也改进了许多PowerShell1.0所存在的缺陷。以下就是我最喜欢的PowerShell2.0十大新特性。 新的cmdlet——PowerShell2.0提供了24个全新的cmdlet。其中有一些cmdlet可以与调试程序、Windows管理规范(WMI)以及后台任务协同工作。我最喜欢的就是“Out-GridView”;这个cmdlet可以通过一个交互式的表格来显示其它命令的结果,这样你就可以对所显示的数据进行分类和搜索了。新的操作符——PowerShell2.0新增了三个非常有用的操作符:“@”(读作“splat”)、“-split”以及“-

  • python生成器详解_Python 生成器

    大家好,又见面了,我是你们的朋友全栈君。生成器利用迭代器,我们可以在每次迭代获取数据(通过next()方法)时按照特定的规律进行生成。但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记录,进而才能根据当前状态生成下一个数据。 为了达到记录当前状态,并配合next()函数进行迭代使用,我们可以采用更简便的语法,即生成器(generator)。生成器是一类特殊的迭代器。 创建生成器方法1要创建一个生成器,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成()>>>L=[x**2forxinrange(5)] >>>L [0,1,4,9,16] >>>G=(x**2forxinrange(5)) >>>G <generatorobject<genexpr>at0x7fb63d218750>复制创建L和G的区别仅在于最外层的[]和(),L是一个列表,而G是一个生成器。我们可以直接打印出列表L的每一个元素,而对于生成器G,我们可以按照迭代器的使用方法来使用,即可以通过next(

  • 3.5 Git 分支 - 远程分支

    3.5Git分支-远程分支 远程分支 远程引用是对远程仓库的引用(指针),包括分支、标签等等。你可以通过 gitls-remote<remote> 来显式地获得远程引用的完整列表,或者通过 gitremoteshow<remote> 获得远程分支的更多信息。然而,一个更常见的做法是利用远程跟踪分支。 远程跟踪分支是远程分支状态的引用。它们是你无法移动的本地引用。一旦你进行了网络通信,Git就会为你移动它们以精确反映远程仓库的状态。请将它们看做书签,这样可以提醒你该分支在远程仓库中的位置就是你最后一次连接到它们的位置。 它们以 <remote>/<branch> 的形式命名。例如,如果你想要看你最后一次与远程仓库 origin 通信时 master 分支的状态,你可以查看 origin/master 分支。你与同事合作解决一个问题并且他们推送了一个 iss53 分支,你可能有自己的本地&nb

  • Redis数据结构之intset

    本文及后续文章,Redis版本均是v3.2.8 上篇文章《Redis数据结构之robj》,我们说到redisobject数据结构,其有5中数据类型:OBJ_STRING,OBJ_LIST, OBJ_SET,OBJ_ZSET,OBJ_HASH。集合对象set有着广泛的实际业务应用场景,它包含的元素无序并且不能重复及集合间的交、并、差等基础的操作。本篇就来说说Redis暴露给我们使用的set集合对象的底层实现-intset。 其实,可以理解为有序整型集合 intset是一个由整数组成的有序集合,从而便于进行二分查找,用于快速地判断一个元素是否属于这个集合。 它在内存分配上与ziplist有些类似,是连续的一整块内存空间,而且对于大整数和小整数采取了不同的编码,尽量对内存的使用进行了优化。 一、intset数据结构定义 typedefstructintset{   uint32_tencoding; //编码类型   uint32_tlength; //intset大小,元素个数   

  • Leetcode:Palindrome Number

    题目链接 Determinewhetheranintegerisapalindrome.Dothiswithoutextraspace. Somehints: Couldnegativeintegersbepalindromes?(ie,-1) Ifyouarethinkingofconvertingtheintegertostring,notetherestrictionofusingextraspace. Youcouldalsotryreversinganinteger.However,ifyouhavesolvedtheproblem"ReverseInteger",youknowthatthereversedintegermightoverflow.Howwouldyouhandlesuchcase? Thereisamoregenericwayofsolvingthisproblem. 注意:oj里面把负数视为非回文数   提示里面说可以把数字倒转过来,如果和原来数字相同那么就是回文数,但是数字倒转后可能越界,比如2147483647倒转后7463847412就超

  • 新汉诺塔

    Description 设有n(n<=50)个大小不等的中空圆盘,按从小到大的顺序从1到n编号。将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A、B、C,这个状态称为初始状态。 现在要求找到一种步数最少的移动方案,使得从初始状态转变为目标状态。 移动时有如下要求: 一次只能移一个盘; 不允许把大盘移到小盘上面。 Analysis 没有头绪的一题,如果圆盘有序放置,是不是题目会简单很多?答案是肯定的。 显而易见,每次只能移动顶层的圆盘,但是此思维类似于爆搜,是不可取的。回到汉诺塔游戏的思路,将n-1个盘子转移走,把自己放到目标杆子上,把n-1个盘子放回来,所以是一个递归的思想。 这题规则有所改变,每个盘子都有自己的目标状态。只能把目标状态中底部的盘子先达到目标,再把另外n-1个盘子弄上去。而瞄准一个盘子怎么把它放上去呢? 首先肯定要把目标点的盘子拾搬,把自己头上的拾搬,最后才能把自己放上去。这显然是正确的,但是拾搬的扔到哪呢?只能扔到另一根柱子上了。 接着,我就没有彻底没有头绪了,因为任意迭套存在小的上面有大环的情况,这个拾搬的策略实在是太复杂了。先写一个初始状态一

  • 《Spring Cloud微服务架构实战》--Rest客户端--Feign

    《SpringCloud微服务架构实战》--客户端--Feign   在SpringCloud集群中,各个角色的通信基于REST服务,因此在调用服务时,就不可避免地需要使用REST服务的请求客户端。 前面的章节中使用了Spring自带的RestTemplate,RestTemplate使用HttpClient发送请求。 本章中,我们将介绍另一个REST客户端:Feign Feign框架已经被集成到SpringCloud的Netflix项目中,使用该框架可以在SpringCloud的集群中更加简单地调用REST服务。   5.1Rest客户端   在学习Feign前,我们先了解一下REST客户端。本节将简单地讲述ApacheCXF与Restlet这两款WebService框架,并使用这两个框架来编写REST客户端,最后再编写一个Feign的HelloWorld例子。 通过此过程,大家可以对Feign有一个初步的印象。如已经掌握这两个REST框架,可直接学习本章后面的内容。   本章中介绍的各个客户端,将会访问8080端口的/person/(personld)和/hel

  • 转载:番外篇 etcd服务无法启动的修复方法

    今天有一个环境的master节点的挂载掉线了,恢复之后该节点的etcd就起不来了。 猜测应该是和其他etcd节点数据不同步导致的,下面我们模拟一下 案例 查看集群组件状态 [root@k8s-master01~]#kubectlgetcs NAMESTATUSMESSAGEERROR schedulerHealthyok controller-managerHealthyok etcd-0Healthy{"health":"true"} etcd-1Healthy{"health":"true"} etcd-2Healthy{"health":"true"} 我们登陆节点(192.168.1.20),删除etcd的数据目录模仿故障 根据配置得知我们的数据目录位置 [Member] ETCD_NAME="etcd-1" ETCD_DATA_DIR="/var/lib/etcd/default.etcd"#数据目录 ETCD_LISTEN_PEER_URLS="https://192.168.1.20:2380" ETCD_LISTEN_CLIENT_URLS="https://192.1

  • 4、ABPZero系列教程之拼多多卖家工具 集成短信发送模块

      ABPZero并没有手机短信发送功能,现在我们来集成一个,为后面注册、登录作铺垫。 阿里云短信服务 首先需要在阿里云开通短信服务,连接地址 开通后,在签名管理中添加一个签名 在模板管理中添加一个模板,如下图所示 最后需要使用阿里云提供的.NET发送短信类库,下面可以直接下载我上传的类库,也可以去官方下载,然后提取我所说的2个类库(aliyun-net-sdk-core.dll、aliyun-net-sdk-dysmsapi.dll) 直接下载文件:https://files.cnblogs.com/files/shensigzs/aliyun-net-sdk.zip (里面包含2个类库,把这2个类库引用到Core项目) .NET发送短信SDK:https://help.aliyun.com/document_detail/59836.html?spm=5176.doc55284.6.573.GaNxg6 安装类库 如下图所示 使用的模块是Abp.Net.Sms,源码地址:https://github.com/berkaroad/Abp.Net.Sms  

  • 类型转换

    AVOIDCASTS C++提供了4种类型转换符: dynamic_cast Adynamic_castsupportstherun-timeidenficationofobjectsaddressedeitherbyapointerorreference. const_cast Aconst_castcastsawaytheconstnessofitsexpression. static_cast Anytypeconversionthatthecompilerperformsimplicitlycanbeexplicitlyrequestedbyusingastatic_cast. doubled=97.0; charch=static_cast<char>(d); 复制 Astatic_castisalsousefultoperformaconversionthatthecompilerwillnotgenerateautomately. void*p=&d; double*dp=static_cast<doubl*>(p); 复制 reinter

  • JxBrowser概述与简单应用

    Q:JxBrowser是什么? JxBrowser是一个跨平台的Java库,允许将基于GoogleChromium的Web浏览器组件集成到JavaSwing/AWT/JavaFX应用程序中。使用JxBrowser,您可以将轻量级Swing/JavaFX组件嵌入到Java应用程序中,以显示现代网页,支持最新的Web标准,如HTML5,CSS3,JavaScript等。 Q:为什么选用JxBrowser? BS结构的优点在于,软件维护和升级方便,只要能上网就能升级了且在很多地方都能够直接使用软件,而不需要安装,前提要能登陆到服务器。 CS结构缺乏通用性,具有较大的局限性,维护和管理的难度大,但是CS结构的交互性强,而且使用CS能与本地的硬件进行交互(如小票打印机、银联pos机、钱箱等……) 虽然BS结构有诸多优点,但当遇到需要与硬件进行交互时,并不能完全满足业务需求,故而采用了BS+CS结合的方式,希望能同时具有CS结构的交互性与BS的灵活性,使用JxBrowser后,客户端相当于一个带有谷歌浏览器内核的定制浏览器,负责与硬件(如打印机、钱箱、POS机等)的交互,同时负责业务网页的显

  • 自定义空间--瀑布流容器

    效果就是添加图片,图片会自动添加到最短的一列中。跟瀑布一样垂下来。 这里说一句  onMeasure 和onLayout会执行两次,如果在方法中去数据不是太好,可以再onChangeSize(),此方法在onMeasure后执行,可以获得控件测量的宽和高(getMeasureWidth、getMeasureHeight)不能获取到(getWidth,getHeight 这两个方法需要在onLayout执行后才有效); <com.kallaite.rxjavademo.customcontrols.CustomImgLayoutandroid:layout_width="match_parent"android:id="@+id/img_layout"android:layout_height="wrap_content"attrs:widthSpec="20"attrs:heightSpec="20"attrs:colums="3"></com.kallaite.rxjavademo.customcontrols.Cu

  • ios 动画:底部标签栏的概念设计

    本文汇集了大量优秀的ios底部标签栏动效设计,并附上技术实现的指南,对于设计师和开发者都提供了很好的灵感来源和学习资源。     我们每天都见到tabbars,它们指引用户,使得他们能够快速在不同的tab中切换,谁说这些移动端导航的设计一定很无聊呢?   让我们来探索tabbars中的有趣动画,我首先关注的是为ios平台设计的作品,并提到了一些在swift中实现tabbars动画的指南。   WeChatTabBarRedesign by AdrianReznicek for platform   Animatedtabbar concept by Cadabra Studio   Cameraapptabbar[iPhoneXedition] concept by OlegFrolov forMagic Unicorn   YogaAppMenuConcept by&n

  • 用MFC(C++)实现拼音搜索

    2015年4月1日更新: 我在github开源了Objective-C版的拼音搜索项目,感兴趣的可以去看看: OC版拼音搜索     最近项目需要实现按照拼音搜索资源。在网上找了一下,这方面的东西太少了。 Java有一个开源的实现,但是没耐心看下去,毕竟对Java不是特别熟练。C++方面大多都是按照字符的编码去获取拼音。这又涉及到GB2312和UTF-8的转换问题。转来转去的,我都晕了。所以就还是自己写一个好了。没用什么比较牛的算法,所以效率上还有很多进步的空间。支持多音字。字库文件可以随时补充。 先把本程序用的的map宏定义一下: #include<map> typedefstd::multimap<CString,CString>CStrCStrMultimap; typedefstd::multimap<CString,CString>::iteratorCStrCStrIt; typedefstd::multimap<int,CString>IntCStrMultimap; typedefstd::mult

相关推荐

推荐阅读