• LinQ动态排序


    LinQ动态排序

    首先修复程序中的一个BUG这个BUG在GridPager类中,把sord修改为sort这个名称填写错误,会导致后台一直无法获取datagrid的排序字段

    本来是没有这一讲的,为了使20行的代码精简成2行,我查阅了一些资料,借鉴了一些大神的建议,首先感谢第八讲中,11楼@nyth和15楼@红颜醉丶帝的建议投递,每一次的的排序要都一个判断这的确很麻烦,我们利用反射来解决这个问题。

    先看原来的代码

    复制代码
     //排序
                if (pager.order == "desc")
                {
                    switch (pager.order)
                    {
                        case "CreateTime":
                            queryData = queryData.OrderByDescending(c => c.CreateTime);
                            break;
                        case "Name":
                            queryData = queryData.OrderByDescending(c => c.Name);
                            break;
                        default:
                            queryData = queryData.OrderByDescending(c => c.CreateTime);
                            break;
                    }
                }
                else
                {
    
                    switch (pager.order)
                    {
                        case "CreateTime":
                            queryData = queryData.OrderBy(c => c.CreateTime);
                            break;
                        case "Name":
                            queryData = queryData.OrderBy(c => c.Name);
                            break;
                        default:
                            queryData = queryData.OrderBy(c => c.CreateTime);
                            break;
                    }
                }
    复制代码

    以上每一次排序都要进行判断,利用反射可以解决这个问题,我把他封装起来了。(需要对反射有一些理解)

    在App.Common中新建LinqHelper类代码如下(下面有3个方法,我都对方法进行了注释,看下就明白)

     View Code

    我们对Sorting的代码分析如下:

    ParameterExpression param = Expression.Parameter(typeof(T), sortExpression);

    我们们传入的类型中找出我们需要进行排序的字段。
    PropertyInfo pi = typeof(T).GetProperty(sortExpression);

    取出要排序字段的相关属性

      Type[] types = new Type[2];
      types[0] = typeof(T); 获得要进行排序的数据集的类型。
      types[1] = pi.PropertyType;  取出我们把什么类型的字段进行排序(即传入参数的值类型)

      Expression expr = Expression.Call(typeof(Queryable), sortingDir, types, source.Expression, Expression.Lambda(Expression.Property(param, sortExpression), param));

    生成排序表达式
      IQueryable<T> query = source.AsQueryable().Provider.CreateQuery<T>(expr);

    执行排序

    现在我们修改一下SysSample的BLL层

    将以上的代码修改为

    queryData = LinqHelper.DataSorting(queryData,pager.sort,pager.order);

    我们的代码顿时精简成了一行,赞一个吧。

     

    作者:YmNets
    出处:http://ymnets.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

     

     

     

    YY一下微信线下支付的场景

     

    在上一篇文章里面提到了 《跨行清算的实现原理》,这次来分析一下线下支付的场景和流程。

    今天看到一篇文章:http://www.huxiu.com/article/23248/1.html?f=chouti  银泰和支付宝线下合作,推广支付宝当面付款的功能

    其实仔细分析一下,觉得当面付这个功能说实在的,对消费者来说,并没有太大的优势,主要表现在以下几点:

    1 当面付的资金要么从支付宝余额支付,要么从关联的快捷银行卡支付。对于大多数用户来说,直接使用信用卡支付即可,为什么要经过支付宝钱包绕一圈,人为增加了一道手续。

    2 线下支付最重要的是支付效率,从个人经验来看,银行卡的支付效率是除现金之外,目前线下支付场景中最快的。耍一下,签个字即可。对于银泰这种大卖场,支付效率最为重要,否则排队的人不耐烦不想买了,最终损失的银行。从当面付的流程来看,先淘出手机,解锁,选择支付宝钱包,在解锁,选择到制定的页面,对准声波发生器,如果一切顺利的话,自然还好,如果不顺利的话,急死你。整个过程要保证柜台网络畅通。我自己体验过,必须网络信号好,手机别套套子,外部环境安静的情况下,支付成功率比较高。

    不过支付宝当面付对于卖场来说,是有一些优势的,主要是费率,银联卡的费率比较高,如果支付宝当面付的费率很低的话,商户可以节约很大一部分成本。但是核心问题不是卖家而是买家是否愿意使用。从支付宝的定位来看,主要是解决支付的问题,那么线下购物是否可以采用类似网上购物的模式,构成一个闭环。自己分析了一下,觉得还是可行的。

    线下支付购物的场景

    1 每当你去大商场买东西的时候,开始的时候发现一个商品,比如裤子比较合身,但是你想看看后面还有更好的,如果没有发现更适合的,你只能重新来到这家店在来买这一件裤子。那能不能和线上购物一样,先保存订单,等全部看完之后,在确定是否需要

    2 在大商场举办打折活动的时候,购买的人非常多,你必须要一点点在柜台前面排队,等待支付。这个过程是同步,必须等待前一个人支付完成之后,后面在支付。而且整个过程你必须排队,一离开就只能重新再排了,如果这个时候你肚子难受,不就郁闷死。

    从上面的线下购物两个场景来看,其实和线上购物比较类似的,在网络上购物,首先是选择商品,然后下单,进入购物车,在对购物车的订单进行确认,进入了收银台,然后支付,在等待收货即可。简化一下线上购物流程:挑选商品——>下单——>在购物车确认订单——>进入收银台——>支付订单——>等待收货。

    类比线上购物,线下是否也可以做成和线上一样了,其实仔细分析一下,两者有着很大的共同点,拿微信举例(淘宝也是可以的,鉴于微信最近比较火,选择微信做例子而已,只要是移动客户端都可以),下面是一个简单的订单支付流程:

    线下购物流程

    FB73CB57 AB9A 4A50 8C04 A8DCACB2B9AC

    下单流程:通过二维码作为中介,订单推送到微信的购物车,微信先把订单保存到本地,你就可以先把订单保存下来,至于卖不卖,可以等到后面在做决定

    确认订单:等用户确认了哪些商品确实需要,那么就可以进行订单确认。在这个时候,订单才推送到财付通(可以是腾讯的一个内部系统),财付通在通知卖场的信息管理管理系统

    进入收银台:用户确定订单之后,到收银台进行支付,选择微信支付,支付成功之后通知卖场,卖场修改订单状态,确认订单已经付款。

    在整个订单支付的过程,完全不需要依赖卖场的柜面,而且是异步进行的,不用排队。你可以一边吃饭,一边完成整个订单的支付过程。

    这里面要解决一个问题:如何知道订单是属于哪个卖场的和属于卖场的那个具体店铺的?

    解决方案1:

    在二维码上做文章,生成一个二维码,这里面包含了卖场,店铺,价格等信息,那这就是线下商铺进入卖场,必须登陆卖场的管理系统,自己生成二维码,然后自己在贴到自己的店铺上,让用户扫。

    解决方案2:

    卖场在微信上开一个公共账号,用户关注公共账号,并输入一个商品ID,公共账号返回商品二维码,系统自动扫描进入购物车。这个ID是卖场的管理系统为商品生成的一个ID。

    显然第二种对于卖场来说是比较合理的,对用户来说也是方便的,卖场获取了用户的信息,用户操作也比较方便,但是必须依赖卖场。

    线下收货流程

    线下购物和线上购物在收货环节也不同,主要体现在,线下可以直接取货。这就需要支付凭证,更重要的是要有发票。支付凭证其实还好处理,微信本身就保存有,主要是发票。这个必须由卖场或者商铺来出具。我在苏宁买电器的时候,貌似是苏宁出具发票,具体的厂家出具保修服务。那么获取发票的流程,其实必须到柜台索要,这个是整个过程中唯一需要到柜台排队的环节。

    NewImage

    这里其实卖场可以优化的环节为:柜台发票和支付分离开的话,对于使用微信支付,直接到获取发票的柜台排队,对于刷卡或者现金支付的,到传统的柜台排队。这个效率也是比较明显。其实可以再想象一下,如果未来有电子发票或者自主打印机发票。那么整个购物环节其实完全和线下实体的柜面脱离。对于用户来说,效率非常高。我在苏宁实体店买过东西,跑上跑下的,那个过程对于一个懒人来说实在是觉得麻烦。

    其实从整个线下的购物过程来看,其实和线上非常类似,但是淘宝系的优势在线下无法体验。对于传统卖场来说,线下支付并不重要,重要的还是购物者的体验以及营销的渠道。接入淘宝对他们来说并没有太大的优势,因为我都来到你卖场这里了,干嘛还要去网上买,上网主要是为了比价。但是微信和淘宝不同的是在于他的渠道价值,这个是线下商户最为看重的,关注过公共平台账号的微信用户体验会非常深,如果你喜欢和星巴克,你去关注星巴克,那么星巴克有什么新品和促销信息,你自然很在意,而星巴克也希望把这些信息通知到消费者,这对于消费者和商户来说是双赢的。比如我就关注了招商微信的公共账户,一个是作为信息提醒,另外一个是像知道最近那些商户刷卡有积分赚等等。为什么是微信,因为他是手机端使用最为频繁的应用,据说已经占领了中国广大的农村。

    GodIsCoder 

    采集博客园文章,用瀑布流+无限滚动展示(附源码)

     

    一 前言

      前段时间一直在了解关于Http相关的知识,然后园子里时不时有园友发关于采集网页信息的文章,然后自己也想试试如何做网页的数据采集,便开始在网找查找相关资料,

    方法有很多种,如 用开源的框架忘了叫什么名了,或者用.net Framework自带的HttpwebRequest对象与HttpwebResponse对象,当然也还有其它对象也可以做到如 WebClient 等,而我选择用HttpwebRequest 与HttpWebResponse来处理。

      经过几个晚上的不断折腾终于把这东西折腾出来了,我的定位就只是用来练手所以不免会有BUG,这个小工具有两个BUG 一个在无限滚动这里,都以经按插件的参数配置了,可它就是不听使唤,老是会自动触发加载事件,不得以我来个限定最多只加载10页的数据。如果有熟悉这个插件的朋友,下载源码后帮忙修改下,我拿它真没折了.......先谢过了~~

    第二个BUG在构造Http请求时有时正常,有时却出现请求超时 比如我在家里测试时,都可以正常运行,而同样的代码放到公司时却出现请求超时,这个问题真心不知道是什么原因引起的,

    这是我写的第二个小工具

    第一个在这里  文件夹管理工具(MVC+zTree+layer)(附源码)

    本项目地址在这里  采集博客园文章工具

    文章还涉及到正则表达示,我总结了一篇相关的文章

    在这里 读懂正则表达式就这么简单

    二 工具介绍与思路介绍

    2.1工具截图

    效果大至就是这样了,样式什么的就没细调了,大伙将就下吧,能看就行了,主要这段时间比较忙,所以匆匆收尾了,还望见谅

    2.2 工具所用到插件

      masonry:

      是 一款非常强大的jQuery动态网格布局插件,可以帮助开发人员快速开发类似剪贴画的界面效果。和CSS中float的效果不太一样的地方在 于,float先水平排列,然后再垂直排列,使用Masonry则垂直排列元素,然后将下一个元素放置到网格中的下一个开发区域。这种效果可以最小化处理 不同高度的元素在垂直方向的间隙

      infinitescroll

      是一个无限循环滚动的插件,做自动分页加载是很好用的,再配合masonry 瀑布流就可以达到 类似于QQ空间自动加载的效果,

          

    三 开发思路

     

      3.1 分析请求

       先用Fiddler 抓取博客园的请求信息大至如下,因为只需要获取文章的信息,不需要做其它操作,所以Cookies部分就可以不考虑,

    只要把请求头的相关信息Copy就行了然后添加到HttpWebRequest对象中

      

         3.2 构造请求 并获取响应信息

      通过HttpWebRequest创建一个请求,然后添加请求头信息,最后获取请求的响应信息到HttpWebResponse对象中,并读取出相应数据。  

    复制代码
                HttpWebRequest request = (HttpWebRequest) WebRequest.Create("http://www.cnblogs.com/");
                request.Accept = "text/plain, */*; q=0.01";
                request.Method = "GET";
                request.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
                request.ContentLength = 0;
                request.ContentType = "keep-alive";
                request.Host = "www.cnblogs.com";
                request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0";
    
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream responStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responStream,Encoding.UTF8);
                string content = reader.ReadToEnd();
    复制代码

      3.3 通过正则取文章基本信息

       个人觉得最难的部分就在用正则匹配出指定数据,因为没有接触过正则,而且正则又不太容易理解,所以学习正则花了一部分时间,并把正则相关的知识总结成了一篇文章

    读懂正则表达式就这么简单 感谢大家的支持。,这里只列取一部分,具体的项目中都有详细的代码 

    复制代码
                        //取推荐
                        regex =new Regex(
                                "<div class="digg">.*<span.*>(?<digNum>.*)" + @"</span>" +
                                ".*<div class="post_item_body">", RegexOptions.Singleline);
                        article.DiggNum = regex.Match(item.Value).Groups["digNum"].Value;
    
                        //取文章标题 需要去除转义字符
                        regex = new Regex("<h3>(?<a>.*)</h3>", RegexOptions.Singleline);
                        string a = regex.Match(item.Value).Groups["a"].Value;
                        regex = new Regex("<a\s.*href="(?<href>.*?)".*>(?<summary>.*)</a>", RegexOptions.Singleline);
                        article.AritcleUrl = regex.Match(a).Groups["href"].Value;
                        article.AritcleTitle = regex.Match(a).Groups["summary"].Value;
    
                        //取作者图片 先取html img标签再取Src
                        regex = new Regex("<a.*>(?<img><img[^>].*>)</a>", RegexOptions.Singleline);
                        string img = regex.Match(item.Value).Groups["img"].Value;
                        regex = new Regex(@"<img.*src=(?<path>.*)s+.*/>", RegexOptions.Singleline);
                        article.AuthorImg = regex.Match(img).Groups["path"].Value.TrimEnd('"').TrimStart('"');
    复制代码

     3.4 把数据返回给插件Masonry

      具体的参数配置官网都有详细的解释,这里就不详细说了,

    复制代码
      $('.container').masonry({
                itemSelector: '.item',
                columnWidth: 230,//一列的宽度 Integer
                isAnimated: true,//使用jquery的布局变化  Boolean  
                animationOptions: {
    
                    Object :{ queue: false, duration: 500 }   //jquery animate属性 渐变效果  
                },
                gutterWidth: 10,//列的间隙 Integer  
                isFitWidth: true,// 适应宽度   Boolean  
                isResizableL: true,// 是否可调整大小 Boolean  
                isRTL: false,//使用从右到左的布局 Boolean  
            });
    复制代码

     3.5  通过infinitescroll自动加载数据

      通过触发这个插件infinitescroll的事件,来达到自动加载的效果,这里要注意的是自动加需要一个div 与a 标签,div是分页的容器初始化后会隐藏,而a标签的href属性则

    是你要自动加载数据的地址,后面的参数 id=2 默认是从第二页开始,会自动累加。刚开始自己在网上找资料时,没人把这两个元素写出来,让我纠结了好久,我说不给地址

    怎么去哪自动加载去啊,找了好久终于让我发现了.....

    <div id="page-nav">
        <a href="/GetArticle/GetArticles/?id=2"></a>
    </div>
    template 的函数返回值就是自动加载后返回的数据可以在DataType属性设定返回的数据格式,注意插件的最后一个回调函数 function (newElements) 要把新的数据添加进瀑布流的布局里就是在这里处理的, 这里的 newElements 其实就是template的返回值,也就是自动加载后重新拼装的数据。
    复制代码
         $('.container').infinitescroll({
                navSelector: '#page-nav',
                nextSelector: '#page-nav a', //下一页选择器
                itemSelector: ".item", //下一页中需要被加载进当前页的块
                extraScrollPx: 150,//滚动条距离底部多少像素的时候开始加载,默认150
                animate: true,
                maxPage:10,//最大页数
                dataType: 'json',
                loading: {
                    //加载效果
                    finishedMsg: 'No more pages to load',
                },
                template: function (data) {
                    //data表示服务端返回的json格式数据,这里需要把data转换成瀑布流块的html格式,然后返回给回到函数
                    var article = '';
                    for (var i in data) {
                        article += "<li class='item'>" +
                       "<a href=" + data[i].AritcleUrl + " target='_blank'><h3> " + data[i].AritcleTitle + "</h3></a>" +
                        "<p>推荐<b>    " + data[i].DiggNum + "</b> <a href=" + data[i].AuthorUrl + "><img src=" + data[i].AuthorImg + " alt='' /> </a></p>" +
                        "<p style='text-indent: 2em'>" + data[i].AritcleSummary + "</p>" +
                       "<p><a href=" + data[i].AuthorUrl + ">" + data[i].Author + "</a>" + data[i].PublishTime + "</p>" +
                        "<p>" + data[i].CommentNum +"  "+data[i].ReadNum + "</p></li>";
                    }
                    return article;
                },
            },
                function (newElements) {
                    //回调函数,用Masonry布局
                    // 当加载时隐藏所有新项目
                    var $newElems = $(newElements).css({ opacity: 0 });
                    // 现在可以显示所有的元素
                    $newElems.animate({ opacity: 1 });
                    $('.container').masonry('appended', $newElems, true);
                   
                }
            );
    复制代码

     通过上面5步就可以把数据正常的加载出来,具体的细节部分喜欢的朋友可以下载源码看看。

    四 总结

      每次接触新的知识我都尽量会把所学的做一个工具出来,以加强自己的印象。我很享受从构思直到开发完成的这一个过程,在这个过程中收获的东西也很多。

    不仅了解了Http相关的知识,还学习了正则与瀑布流和无限滚动,我会继续以这种方式一直走下去....

    如果您觉得本文有给您带来一点收获,不妨点个推荐,为我的付出支持一下,谢谢~

    如果希望在技术的道路上能有更多的朋友,那就关注下我吧,让我们一起在技术的路上奔跑

     
     

  • 相关阅读:
    nginx重启命令
    Java中Vector笔记
    JAVA中字符串比较equals()和equalsIgnoreCase()的区别
    HashMap和TreeMap的常用排序方法
    Logger用法
    HashMap和Hashtable的区别
    class.getDeclaredFields()与class.getFields()
    java中 文件压缩处理
    Java远程执行Shell命令
    python 学习笔记 redis操作
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3448624.html
Copyright © 2020-2023  润新知