扩展方法学习发展之路

大学学习的java,工作后转成了C#,由于工作需要,全力去学习了C#,学习中,相信大家都会有相同的疑惑,在判断一个字符串是否为空的时候总会用到string.IsNullOrEmpty(s)这个方法,最开始就想到了是不是反射,后面才知道这是c#的扩展方法,后面的内容慢慢讲解我对扩展方法由浅到深的理解与用法。

1:扩展方法的自定义实现,我这里特别用到了判断类型是否为数值类型的方法(可以去比较学习下),里面子定义了4个扩展方法

 1 namespace ConsoleApplication1
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             var i = 32;  
 8             System.Console.WriteLine(i.GetType().IsNumericType());
 9             System.Console.ReadKey();     
10         }
11     }
12 
13     public static class TestExtension
14     {
15         //老外的代码
16         public static bool IsNumeric(this Type dataType)
17         {
18             if (dataType == null)
19                 throw new ArgumentNullException("dataType");
20 
21             return (dataType == typeof(int)
22                     || dataType == typeof(double)
23                     || dataType == typeof(long)
24                     || dataType == typeof(short)
25                     || dataType == typeof(float)
26                     || dataType == typeof(Int16)
27                     || dataType == typeof(Int32)
28                     || dataType == typeof(Int64)
29                     || dataType == typeof(uint)
30                     || dataType == typeof(UInt16)
31                     || dataType == typeof(UInt32)
32                     || dataType == typeof(UInt64)
33                     || dataType == typeof(sbyte)
34                     || dataType == typeof(Single)
35                    );
36         }
37         /// <summary>
38         /// 判断是否为数值类型。
39         /// </summary>
40         /// <param name="t">要判断的类型</param>
41         /// <returns>是否为数值类型</returns>
42         public static bool IsNumericType(this Type t)
43         {
44             var tc = Type.GetTypeCode(t);
45             return (t.IsPrimitive && t.IsValueType && !t.IsEnum && tc != TypeCode.Char && tc != TypeCode.Boolean) || tc == TypeCode.Decimal;
46         }
47 
48         /// <summary>
49         /// 判断是否为可空数值类型。
50         /// </summary>
51         /// <param name="t">要判断的类型</param>
52         /// <returns>是否为可空数值类型</returns>
53         public static bool IsNumericOrNullableNumericType(this Type t)
54         {
55             return t.IsNumericType() || (t.IsNullableType() && t.GetGenericArguments()[0].IsNumericType());
56         }
57 
58         /// <summary>
59         /// 判断是否为可空类型。
60         /// 注意,直接调用可空对象的.GetType()方法返回的会是其泛型值的实际类型,用其进行此判断肯定返回false。
61         /// </summary>
62         /// <param name="t">要判断的类型</param>
63         /// <returns>是否为可空类型</returns>
64         public static bool IsNullableType(this Type t)
65         {
66             return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
67         }
68 
69     }
70 }

2:通过上面的列子可能就只能看出它使用上更为便捷而已,但当我接触到Linq,才发现扩展方法的强大,自己也学着参考改造下Linq的构造方法以增加增加所需要的功能

 1 public static class QueryableExtensions
 2     {
 3         public static IQueryable<T> OrderBy<T>(this IQueryable<T> queryable, string propertyName)
 4         {
 5             return QueryableHelper<T>.OrderBy(queryable, propertyName, false);
 6         }
 7         public static IQueryable<T> OrderBy<T>(this IQueryable<T> queryable, string propertyName, bool desc)
 8         {
 9             return QueryableHelper<T>.OrderBy(queryable, propertyName, desc);
10         }
11      
12         static class QueryableHelper<T>
13         {
14             //为了缓存表达式树
15             private static Dictionary<string, LambdaExpression> cache = new Dictionary<string, LambdaExpression>();
16             public static IQueryable<T> OrderBy(IQueryable<T> queryable, string propertyName, bool   desc)
17             {
18 
19                 dynamic keySelector = GetLambdaExpression(propertyName);
20                 return desc ? Queryable.OrderByDescending(queryable, keySelector) : Queryable.OrderBy(queryable, keySelector);
21             }
22             private static LambdaExpression GetLambdaExpression(string propertyName)
23             {
24                 if (cache.ContainsKey(propertyName)) return cache[propertyName];
25                 var param = Expression.Parameter(typeof(T));
26                 var body = Expression.Property(param, propertyName);
27                 var keySelector = Expression.Lambda(body, param);
28                 cache[propertyName] = keySelector;
29                 return keySelector;
30             }
31         }
32     }

4:对于数据库的操作,也可以使用扩展方法,我上篇随笔也说了,项目用了IOC,没有在数据库这块用到扩展方法,这可以参考http://www.cnblogs.com/xiaotuni/archive/2012/05/29/2523683.html

5:当使用到MVC框架的时候,看到前端的页面使用Html.BeginForm等一些相同格式语法的时候,我马上意识到这就是MVC里面的扩展方法,转而想是否可以自己也写一些扩展方法,方便自己使用,首先我想到前端Table的遍历,分页等,并着手全部实现,并应用于项目中

Table的遍历,我们在后台写好一个扩展方法类

 1  public static class RazorExtensions
 2     {
 3         public static HelperResult /*List*/ Repeat<T>(this IEnumerable<T> items,
 4             Func<T, HelperResult> template)
 5         {
 6             if (items == null) 
 7                 return new HelperResult(t => t.Write(""));
 8 
 9             return new HelperResult(writer =>
10             {
11                 foreach (var item in items)
12                 {
13                     template(item).WriteTo(writer);
14                 }
15             });
16         }
17 }

前端我们引用他的命名空间,如下方式调用:

<tbody>
                @Model.Repeat(
                    @<tr>
                         <td><ahref="/order/catalog/new/@item.ContractNo">@item.ContractNo</a></td>  
                         <td>@item.StrokeNo</td>
                         <td>@item.StrokeDesc</td>                  
                         <td>@item.ContractStatus</td>
                         <td>@item.DeptNo</td>
                         <td>@item.Season</td>
                         <td>@item.SupplierSeries</td>
                         <td>@item.CountryCode</td>
                         <td>@item.ProductDesc</td>
                         <td>@item.DateLastModified</td>
                         <td>@item.CreatedTime.Format()</td>
                     </tr>)
            </tbody>

分页控件的实现:

后台:首先我们必须有一个page类

namespace WebPrint.Web.Mvc.Pager
{
    public class PagerOptions
    {
        public PagerOptions()
        {
            AutoHide = true;
            PageIndexParameterName = "pageindex";
            NumericPagerItemCount = 10;
            AlwaysShowFirstLastPageNumber = false;
            ShowPrevNext = true;
            NextPageText = "&gt;";
            PrevPageText = "&lt;";
            ShowNumericPagerItems = true;
            ShowFirstLast = true;
            FirstPageText = "&lt;&lt;";
            LastPageText = "&gt;&gt";
            ShowMorePagerItems = true;
            MorePageText = "...";
            ShowDisabledPagerItems = true;
            PagerItemsSeperator = "  ";
            ContainerTagName = "div";
            InvalidPageIndexErrorMessage = "页索引无效";
            PageIndexOutOfRangeErrorMessage = "页索引超出范围";
            MaxPageIndex = 0;
            FirstPageRouteName = null;
        }
        /// <summary>
        /// 首页使用的路由名称(无页索引参数)
        /// </summary>
        public string FirstPageRouteName { get; set; }
        /// <summary>
        /// 当总页数只有一页时是否自动隐藏
        /// </summary>
        public bool AutoHide { get; set; }
        /// <summary>
        /// 页索引超出范围时显示的错误消息
        /// </summary>
        public string PageIndexOutOfRangeErrorMessage { get; set; }
        /// <summary>
        /// 页索引无效时显示的错误消息
        /// </summary>
        public string InvalidPageIndexErrorMessage { get; set; }
        /// <summary>
        /// url中页索引参数的名称
        /// </summary>
        public string PageIndexParameterName { get; set; }

        private string _containerTagName;
        /// <summary>
        /// 分页控件html容器标签名,默认为div
        /// </summary>
        public string ContainerTagName
        {
            get
            {
                return _containerTagName;
            }
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new System.ArgumentException("ContainerTagName不能为null或空字符串", "ContainerTagName");
                _containerTagName = value;
            }
        }
        /// <summary>
        /// whether or not show first and last numeric page number
        /// </summary>
        public bool AlwaysShowFirstLastPageNumber { get; set; }
        /// <summary>
        /// 显示的最大数字页索引按钮数
        /// </summary>
        public int NumericPagerItemCount { get; set; }
        /// <summary>
        /// 是否显示上页和下页
        /// </summary>
        public bool ShowPrevNext { get; set; }
        /// <summary>
        /// 上一页文本
        /// </summary>
        public string PrevPageText { get; set; }
        /// <summary>
        /// 下一页文本
        /// </summary>
        public string NextPageText { get; set; }
        /// <summary>
        /// 是否显示数字页索引按钮及更多页按钮
        /// </summary>
        public bool ShowNumericPagerItems { get; set; }
        /// <summary>
        /// 是否显示第一页和最后一页
        /// </summary>
        public bool ShowFirstLast { get; set; }
        /// <summary>
        /// 第一页文本
        /// </summary>
        public string FirstPageText { get; set; }
        /// <summary>
        /// 最后一页文本
        /// </summary>
        public string LastPageText { get; set; }
        /// <summary>
        /// 是否显示更多页按钮
        /// </summary>
        public bool ShowMorePagerItems { get; set; }
        /// <summary>
        /// 更多页按钮文本
        /// </summary>
        public string MorePageText { get; set; }
        /// <summary>
        /// 包含分页控件的父容器标签的ID
        /// </summary>
        public string Id { get; set; }
        /// <summary>
        /// CSS样式类
        /// </summary>
        public string CssClass { get; set; }
        /// <summary>
        /// whether or not show disabled navigation buttons
        /// </summary>
        public bool ShowDisabledPagerItems { get; set; }
        /// <summary>
        /// 分页元素之间的分隔符,默认为两个html空格(  )
        /// </summary>
        public string PagerItemsSeperator { get; set; }
        /// <summary>
        /// 限制显示的最大页数,默认值为0,即根据总记录数算出的总页数
        /// </summary>
        public int MaxPageIndex { get; set; }
    }
}

2个生成分页控件HTML代码的类

using System;
using System.Web.Mvc;
using System.Web.Routing;
using WebPrint.Model.Helper;

namespace WebPrint.Web.Mvc.Pager
{
    public static class PagerHelper
    {
        #region Html Pager

        private static MvcHtmlString Pager(this HtmlHelper helper, int totalItemCount, int pageSize, int pageIndex,
            string actionName, string controllerName,
            PagerOptions pagerOptions, string routeName, object routeValues, object htmlAttributes)
        {
            var totalPageCount = (int) Math.Ceiling(totalItemCount/(double) pageSize);
            var builder = new PagerBuilder
                (
                helper,
                actionName,
                controllerName,
                totalItemCount,
                totalPageCount,
                pageIndex,
                pageSize,
                pagerOptions,
                routeName,
                new RouteValueDictionary(routeValues),
                new RouteValueDictionary(htmlAttributes)
                );
            return builder.RenderPager();
        }

        public static MvcHtmlString Pager(this HtmlHelper helper, IPagedList pagedList, PagerOptions pagerOptions)
        {
            //if (pagedList == null)
            //    return Pager(helper, pagerOptions, null);
            return Pager(helper, pagedList.RecordsCount, pagedList.PageSize, pagedList.PageIndex, null, null,
                pagerOptions, null, null, null);
        }

        #endregion
    }
}


/*
 ASP.NET MvcPager 分页组件
 Copyright@杨涛\Webdiyer (http://www.webdiyer.com)
 Source code released under Ms-PL license
 */

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace WebPrint.Web.Mvc.Pager
{
    internal class PagerBuilder
    {
        private readonly HtmlHelper html;
        private readonly string actionName;
        private readonly string controllerName;
        private readonly int totalPageCount = 1;
        private readonly int totalRecordCount = 1;
        private readonly int pageIndex;
        private readonly int pageSize;
        private readonly PagerOptions pagerOptions;
        private readonly RouteValueDictionary routeValues;
        private readonly string routeName;
        private readonly int startPageIndex = 1;
        private readonly int endPageIndex = 1;
        private IDictionary<string, object> htmlAttributes;

        private const string CopyrightText =
            "\r\n<!--MvcPager v2.0 for ASP.NET MVC 4.0+ © 2009-2013 Webdiyer (http://www.webdiyer.com)-->\r\n";

        /// <summary>
        /// 适用于PagedList为null时
        /// </summary>
        //internal PagerBuilder(HtmlHelper html,PagerOptions pagerOptions, IDictionary<string, object> htmlAttributes)
        //{
        //    if (pagerOptions == null)
        //        pagerOptions = new PagerOptions();
        //    this.html = html;
        //    this.pagerOptions = pagerOptions;
        //    this.htmlAttributes = htmlAttributes;
        //}
        internal PagerBuilder(HtmlHelper html, string actionName, string controllerName, int totalRecordCount,
            int totalPageCount, int pageIndex, int pageSize, PagerOptions pagerOptions, string routeName,
            RouteValueDictionary routeValues,
            IDictionary<string, object> htmlAttributes)
        {
            if (pagerOptions == null)
                pagerOptions = new PagerOptions();
            this.html = html;
            this.actionName = actionName;
            this.controllerName = controllerName;
            this.totalRecordCount = totalRecordCount;
            if (pagerOptions.MaxPageIndex == 0 || pagerOptions.MaxPageIndex > totalPageCount)
                this.totalPageCount = totalPageCount;
            else
                this.totalPageCount = pagerOptions.MaxPageIndex;
            this.pageIndex = pageIndex;
            this.pageSize = pageSize;
            this.pagerOptions = pagerOptions;
            this.routeName = routeName;
            this.routeValues = routeValues;
            this.htmlAttributes = htmlAttributes;
            // start page index
            startPageIndex = pageIndex - (pagerOptions.NumericPagerItemCount/2);
            if (startPageIndex + pagerOptions.NumericPagerItemCount > this.totalPageCount)
                startPageIndex = this.totalPageCount + 1 - pagerOptions.NumericPagerItemCount;
            if (startPageIndex < 1)
                startPageIndex = 1;
            // end page index
            endPageIndex = startPageIndex + this.pagerOptions.NumericPagerItemCount - 1;
            if (endPageIndex > this.totalPageCount)
                endPageIndex = this.totalPageCount;
        }

        private void AddPrevious(ICollection<PagerItem> results)
        {
            var item = new PagerItem(pagerOptions.PrevPageText, pageIndex - 1, pageIndex == 1, PagerItemType.PrevPage);
            if (!item.Disabled || (item.Disabled && pagerOptions.ShowDisabledPagerItems))
                results.Add(item);
        }

        private void AddFirst(ICollection<PagerItem> results)
        {
            var item = new PagerItem(pagerOptions.FirstPageText, 1, pageIndex == 1, PagerItemType.FirstPage);
            //只有导航按钮未被禁用,或导航按钮被禁用但ShowDisabledPagerItems=true时才添加
            if (!item.Disabled || (item.Disabled && pagerOptions.ShowDisabledPagerItems))
                results.Add(item);
        }

        private void AddMoreBefore(ICollection<PagerItem> results)
        {
            if (startPageIndex > 1 && pagerOptions.ShowMorePagerItems)
            {
                var index = startPageIndex - 1;
                if (index < 1) index = 1;
                var item = new PagerItem(pagerOptions.MorePageText, index, false, PagerItemType.MorePage);
                results.Add(item);
            }
        }

        private void AddPageNumbers(ICollection<PagerItem> results)
        {
            for (var pageIndex = startPageIndex; pageIndex <= endPageIndex; pageIndex++)
            {
                var text = pageIndex.ToString(CultureInfo.InvariantCulture);
                //if (pageIndex == this.pageIndex && !string.IsNullOrEmpty(pagerOptions.CurrentPageNumberFormatString))
                //    text = String.Format(pagerOptions.CurrentPageNumberFormatString, text);
                //else if (!string.IsNullOrEmpty(pagerOptions.PageNumberFormatString))
                //    text = String.Format(pagerOptions.PageNumberFormatString, text);
                var item = new PagerItem(text, pageIndex, false, PagerItemType.NumericPage);
                results.Add(item);
            }
        }

        private void AddMoreAfter(ICollection<PagerItem> results)
        {
            if (endPageIndex < totalPageCount)
            {
                var index = startPageIndex + pagerOptions.NumericPagerItemCount;
                if (index > totalPageCount)
                {
                    index = totalPageCount;
                }
                var item = new PagerItem(pagerOptions.MorePageText, index, false, PagerItemType.MorePage);
                results.Add(item);
            }
        }

        private void AddNext(ICollection<PagerItem> results)
        {
            var item = new PagerItem(pagerOptions.NextPageText, pageIndex + 1, pageIndex >= totalPageCount,
                PagerItemType.NextPage);
            if (!item.Disabled || (item.Disabled && pagerOptions.ShowDisabledPagerItems))
                results.Add(item);
        }

        private void AddLast(ICollection<PagerItem> results)
        {
            var item = new PagerItem(pagerOptions.LastPageText, totalPageCount, pageIndex >= totalPageCount,
                PagerItemType.LastPage);
            if (!item.Disabled || (item.Disabled && pagerOptions.ShowDisabledPagerItems))
                results.Add(item);
        }

        /// <summary>
        /// 根据页索引生成分页导航Url
        /// </summary>
        /// <param name="pageIndex">要生成导航链接的页索引</param>
        /// <returns>分页导航链接Url</returns>
        private string GenerateUrl(int pageIndex)
        {
            ViewContext viewContext = html.ViewContext;
            //若要生成url的页索引小于1或大于总页数或等于当前页索引时,无需生成分页导航链接
            if (pageIndex > totalPageCount || pageIndex == this.pageIndex)
                return null;
            var routeValues1 = new RouteValueDictionary(viewContext.RouteData.Values);
            AddQueryStringToRouteValues(routeValues1, viewContext);
            if (this.routeValues != null && this.routeValues.Count > 0)
            {
                foreach (var de in this.routeValues)
                {
                    if (!routeValues1.ContainsKey(de.Key))
                    {
                        routeValues1.Add(de.Key, de.Value);
                    }
                    else
                    {
                        routeValues1[de.Key] = de.Value; //手动添加的RouteValues具有高优先级
                    }
                }
            }
            var pageValue = viewContext.RouteData.Values[pagerOptions.PageIndexParameterName];
            string routeName = this.routeName;
            // 设置Route Value中的分页导航Url参数值,pageIndex为0时生成适用于脚本的导航链接
            if (pageIndex == 0)
                routeValues1[pagerOptions.PageIndexParameterName] = "__" + pagerOptions.PageIndexParameterName + "__";
            else
            {
                if (pageIndex == 1)
                {
                    if (!string.IsNullOrWhiteSpace(pagerOptions.FirstPageRouteName))
                        //如果显式指定了FirstPageRouteName,则使用此Route
                    {
                        routeName = pagerOptions.FirstPageRouteName;
                        routeValues1.Remove(pagerOptions.PageIndexParameterName); //去除页索引参数
                        viewContext.RouteData.Values.Remove(pagerOptions.PageIndexParameterName);
                    }
                    else
                    {
                        var curRoute = viewContext.RouteData.Route as Route;
                        //判断当前Route是否为Route类型,如果是,则判断该Route中页索引参数默认值是否为UrlParameter.Optional,或页索引参数是否存在于该Route Url的参数列表中,如果参数默认值为UrlParameter.Optional或分页参数名不存在于Route Url参数中,则从当前的RouteValue列表中去除该参数
                        if (curRoute != null &&
                            (curRoute.Defaults[pagerOptions.PageIndexParameterName] == UrlParameter.Optional ||
                             !curRoute.Url.Contains("{" + pagerOptions.PageIndexParameterName + "}")))
                        {
                            routeValues1.Remove(pagerOptions.PageIndexParameterName); //去除页索引参数
                            viewContext.RouteData.Values.Remove(pagerOptions.PageIndexParameterName);
                        }
                        else
                        {
                            routeValues1[pagerOptions.PageIndexParameterName] = pageIndex;
                        }
                    }
                }
                else
                {
                    routeValues1[pagerOptions.PageIndexParameterName] = pageIndex;
                }
            }
            var routes = html.RouteCollection;
            string url;
            if (!string.IsNullOrEmpty(routeName))
                url = UrlHelper.GenerateUrl(routeName, actionName, controllerName, routeValues1, routes,
                    viewContext.RequestContext, false);
            else
                url = UrlHelper.GenerateUrl(null, actionName, controllerName, routeValues1, routes,
                    viewContext.RequestContext, false);
            if (pageValue != null)
                viewContext.RouteData.Values[pagerOptions.PageIndexParameterName] = pageValue;
            return url;
        }

        /// <summary>
        /// 生成最终的分页Html代码
        /// </summary>
        /// <returns></returns>
        internal MvcHtmlString RenderPager()
        {
            //return null if total page count less than or equal to 1
            if (totalPageCount <= 1 && pagerOptions.AutoHide)
                return MvcHtmlString.Create(CopyrightText);
            //Display error message if pageIndex out of range
            if ((pageIndex > totalPageCount && totalPageCount > 0) || pageIndex < 1)
            {
                return
                    MvcHtmlString.Create(string.Format("{0}<div style=\"color:red;font-weight:bold\">{1}</div>{0}",
                        CopyrightText, pagerOptions.PageIndexOutOfRangeErrorMessage));
            }

            var pagerItems = new List<PagerItem>();
            //First page
            if (pagerOptions.ShowFirstLast)
                AddFirst(pagerItems);
            // Prev page
            if (pagerOptions.ShowPrevNext)
                AddPrevious(pagerItems);
            if (pagerOptions.ShowNumericPagerItems)
            {
                if (pagerOptions.AlwaysShowFirstLastPageNumber && startPageIndex > 1)
                    pagerItems.Add(new PagerItem("1", 1, false, PagerItemType.NumericPage));
                // more page before numeric page buttons
                if (pagerOptions.ShowMorePagerItems &&
                    ((!pagerOptions.AlwaysShowFirstLastPageNumber && startPageIndex > 1) ||
                     (pagerOptions.AlwaysShowFirstLastPageNumber && startPageIndex > 2)))
                    AddMoreBefore(pagerItems);
                // numeric page
                AddPageNumbers(pagerItems);
                // more page after numeric page buttons
                if (pagerOptions.ShowMorePagerItems &&
                    ((!pagerOptions.AlwaysShowFirstLastPageNumber && endPageIndex < totalPageCount) ||
                     (pagerOptions.AlwaysShowFirstLastPageNumber && totalPageCount > endPageIndex + 1)))
                    AddMoreAfter(pagerItems);
                if (pagerOptions.AlwaysShowFirstLastPageNumber && endPageIndex < totalPageCount)
                    pagerItems.Add(new PagerItem(totalPageCount.ToString(CultureInfo.InvariantCulture), totalPageCount,
                        false,
                        PagerItemType.NumericPage));
            }
            // Next page
            if (pagerOptions.ShowPrevNext)
                AddNext(pagerItems);
            //Last page
            if (pagerOptions.ShowFirstLast)
                AddLast(pagerItems);
            var sb = new StringBuilder();

            foreach (PagerItem item in pagerItems)
            {
                sb.Append(GeneratePagerElement(item));
            }

            var tb = new TagBuilder(pagerOptions.ContainerTagName);
            if (!string.IsNullOrEmpty(pagerOptions.Id))
                tb.GenerateId(pagerOptions.Id);
            if (!string.IsNullOrEmpty(pagerOptions.CssClass))
                tb.AddCssClass(pagerOptions.CssClass);
            tb.MergeAttributes(htmlAttributes, true);
            sb.Length -= pagerOptions.PagerItemsSeperator.Length;

            var startRecords = ((pageIndex - 1)*pageSize) + 1;
            var endRecords = pageIndex*pageSize;
            if (endRecords > totalRecordCount)
                endRecords = totalRecordCount;

            var recordsCountText =
                string.Format("<span class=\"summary\">{0}&nbsp;-&nbsp;{1},&nbsp;{2}&nbsp;records</span>",
                    startRecords, endRecords, totalRecordCount);
            tb.InnerHtml = sb.ToString() + recordsCountText;

            return
                MvcHtmlString.Create(CopyrightText + /*pagerScript +*/ tb.ToString(TagRenderMode.Normal) + CopyrightText);
        }

        private MvcHtmlString GeneratePagerElement(PagerItem item)
        {
            //pager item link
            string url = GenerateUrl(item.PageIndex);
            if (item.Disabled) //first,last,next or previous page
                return CreateWrappedPagerElement(item,
                    String.Format("<a class=\"disabled\" disabled=\"disabled\">{0}</a>", item.Text));
            return CreateWrappedPagerElement(item,
                string.IsNullOrEmpty(url)
                    ? HttpUtility.HtmlEncode(item.Text)
                    : String.Format("<a href=\"{0}\">{1}</a>", url, item.Text));
        }

        private MvcHtmlString CreateWrappedPagerElement(PagerItem item, string el)
        {
            string navStr = el;
            switch (item.Type)
            {
                case PagerItemType.FirstPage:
                case PagerItemType.LastPage:
                case PagerItemType.NextPage:
                case PagerItemType.PrevPage:
                    break;
                case PagerItemType.MorePage:
                    break;
                case PagerItemType.NumericPage:
                    if (item.PageIndex == pageIndex)
                    {
                        navStr = string.Format("<a href=\"javascript:void(0);\" class=\"current\">{0}</a>", el);
                    }
                    break;
            }
            return MvcHtmlString.Create(navStr + pagerOptions.PagerItemsSeperator);
        }

        private void AddQueryStringToRouteValues(RouteValueDictionary routeValues, ViewContext viewContext)
        {
            if (routeValues == null)
                routeValues = new RouteValueDictionary();
            var rq = viewContext.HttpContext.Request.QueryString;
            if (rq != null && rq.Count > 0)
            {
                var invalidParams = new[]
                {"x-requested-with", "xmlhttprequest", pagerOptions.PageIndexParameterName.ToLower()};
                foreach (string key in rq.Keys)
                {
                    // 添加url参数到路由中
                    if (!string.IsNullOrEmpty(key) && Array.IndexOf(invalidParams, key.ToLower()) < 0)
                    {
                        var kv = rq[key];
                        routeValues[key] = kv;
                    }
                }
            }
        }
    }
}

使用扩展方法:

public static MvcHtmlString Paginaton(this HtmlHelper helper, IPagedList pagedList)
        {
            var pagerOptions = new PagerOptions
            {
                PageIndexParameterName = "page",
                CssClass = "pagination",
                ShowFirstLast = false,
                AlwaysShowFirstLastPageNumber = true,
                ShowMorePagerItems = true,
                NumericPagerItemCount = 5,
                PagerItemsSeperator = string.Empty,
            };

            return helper.Pager(pagedList, pagerOptions);
        }

前端直接引用调用:

<div class="pagination_div">
   @Html.Paginaton(Model)
</div>

总结:相对于鹤冲天大哥的见解,我对于扩张方法的使用差的太远,但一般的场景也可以用到扩展方法的地方都还是可以轻松应对,所以我们平常就该对深入的学习认识他,才能在后面应用自如

 

posted @ 2015-06-01 16:23  稳稳的河  阅读(1147)  评论(2编辑  收藏  举报