zoukankan      html  css  js  c++  java
  • (转)一步一步Asp.Net MVC系列_权限管理之权限控制

    原文地址:http://www.cnblogs.com/mysweet/archive/2012/08/05/2623687.html

    在权限管理中一个很重要的就是关于权限的拦截验证问题,特别是我们在webform中的验证,比纯winform要更复杂,winform可以通过验证把按钮隐藏或者禁用的方式,但是在web中我们不能仅仅通过隐藏按钮,不显示菜单/按钮之类的手段,因为客户端的代码都是透明的,如果我们不在服务端把好关,那么权限根本就无从谈起,我们必须彻底的进行验证,每一步动作都要进行验证,客户端的每一个ajax提交都要进行验证,如果任何一个ajax 动作都做过验证了,那么至少可以保证基本的安全性了.

    在纯webform中,我们通常怎么来进行权限控制呢?

    一般情况下,设计基类然后,在基类写好验证方法,子类调用并验证

    我们来看看启航动力的开源CMS怎么进行的验证:

       1:  using System;
       2:  using System.Collections.Generic;
       3:  using System.Text;
       4:  using System.Web;
       5:  using System.Web.UI.WebControls;
       6:  using DTcms.Common;
       7:   
       8:  namespace DTcms.Web.UI
       9:  {
      10:      public class ManagePage : System.Web.UI.Page
      11:      {
      12:          protected internal Model.siteconfig siteConfig;
      13:   
      14:          public ManagePage()
      15:          {
      16:              this.Load += new EventHandler(ManagePage_Load);
      17:              siteConfig = new BLL.siteconfig().loadConfig(Utils.GetXmlMapPath("Configpath"));
      18:          }
      19:   
      20:          private void ManagePage_Load(object sender, EventArgs e)
      21:          {
      22:              //判断管理员是否登录
      23:              if (!IsAdminLogin())
      24:              {
      25:                  Response.Write("<script>parent.location.href='" + siteConfig.webpath + siteConfig.webmanagepath + "/login.aspx'</script>");
      26:                  Response.End();
      27:              }
      28:          }
      29:   
      30:          #region 管理员============================================
      31:          /// <summary>
      32:          /// 判断管理员是否已经登录(解决Session超时问题)
      33:          /// </summary>
      34:          public bool IsAdminLogin()
      35:          {
      36:              //如果Session为Null
      37:              if (Session[DTKeys.SESSION_ADMIN_INFO] != null)
      38:              {
      39:                  return true;
      40:              }
      41:              else
      42:              {
      43:                  //检查Cookies
      44:                  string adminname = Utils.GetCookie("AdminName", "DTcms"); //解密用户名
      45:                  string adminpwd = Utils.GetCookie("AdminPwd", "DTcms");
      46:                  if (adminname != "" && adminpwd != "")
      47:                  {
      48:                      BLL.manager bll = new BLL.manager();
      49:                      Model.manager model = bll.GetModel(adminname, adminpwd);
      50:                      if (model != null)
      51:                      {
      52:                          Session[DTKeys.SESSION_ADMIN_INFO] = model;
      53:                          return true;
      54:                      }
      55:                  }
      56:              }
      57:              return false;
      58:          }
      59:   
      60:          /// <summary>
      61:          /// 取得管理员信息
      62:          /// </summary>
      63:          public Model.manager GetAdminInfo()
      64:          {
      65:              if (IsAdminLogin())
      66:              {
      67:                  Model.manager model = Session[DTKeys.SESSION_ADMIN_INFO] as Model.manager;
      68:                  if (model != null)
      69:                  {
      70:                      return model;
      71:                  }
      72:              }
      73:              return null;
      74:          }
      75:   
      76:          /// <summary>
      77:          /// 检查管理员权限
      78:          /// </summary>
      79:          /// <param name="channel_id">频道ID</param>
      80:          /// <param name="action_type">操作类型</param>
      81:          public void ChkAdminLevel(int channel_id, string action_type)
      82:          {
      83:              Model.manager model = GetAdminInfo();
      84:              BLL.manager_role bll = new BLL.manager_role();
      85:              bool result = bll.Exists(model.role_id, channel_id, action_type);
      86:              if (!result)
      87:              {
      88:                  string msbox = "parent.f_errorTab(\"错误提示\", \"您没有管理该页面的权限,请勿尝试非法进入!\")";
      89:                  //ClientScript.RegisterClientScriptBlock(Page.GetType(), "JsPrint", msbox.ToString(), true);  //修正BUG
      90:                  Response.Write("<script type=\"text/javascript\">" + msbox + "</script>");
      91:                  Response.End();
      92:              }
      93:          }
      94:   
      95:          /// <summary>
      96:          /// 检查管理员权限
      97:          /// </summary>
      98:          /// <param name="channel_name">栏目名称</param>
      99:          /// <param name="action_type">操作类型</param>
     100:          public void ChkAdminLevel(string channel_name, string action_type)
     101:          {
     102:              Model.manager model = GetAdminInfo();
     103:              BLL.manager_role bll = new BLL.manager_role();
     104:              bool result = bll.Exists(model.role_id, channel_name, action_type);
     105:              if (!result)
     106:              {
     107:                  string msbox = "parent.f_errorTab(\"错误提示\", \"您没有管理该页面的权限,请勿尝试非法进入!\")";
     108:                  //ClientScript.RegisterClientScriptBlock(Page.GetType(), "JsPrint", msbox.ToString(), true);  //修正BUG
     109:                  Response.Write("<script type=\"text/javascript\">" + msbox + "</script>");
     110:                  Response.End();
     111:              }
     112:          }
     113:   
     114:          /// <summary>
     115:          /// 检查管理员权限
     116:          /// </summary>
     117:          /// <param name="channel_name">栏目名称</param>
     118:          /// <param name="action_type">操作类型</param>
     119:          /// <returns>bool</returns>
     120:          public bool IsAdminLevel(string channel_name, string action_type)
     121:          {
     122:              Model.manager model = GetAdminInfo();
     123:              BLL.manager_role bll = new BLL.manager_role();
     124:              return bll.Exists(model.role_id, channel_name, action_type);
     125:          }
     126:   
     127:          #endregion
     128:   
     129:          #region 枚举==============================================
     130:   
     131:          /// <summary>
     132:          /// 统一管理操作枚举
     133:          /// </summary>
     134:          public enum ActionEnum
     135:          {
     136:              /// <summary>
     137:              /// 所有
     138:              /// </summary>
     139:              All,
     140:              /// <summary>
     141:              /// 查看
     142:              /// </summary>
     143:              View,
     144:              /// <summary>
     145:              /// 添加
     146:              /// </summary>
     147:              Add,
     148:              /// <summary>
     149:              /// 修改
     150:              /// </summary>
     151:              Edit,
     152:              /// <summary>
     153:              /// 删除
     154:              /// </summary>
     155:              Delete
     156:          }
     157:   
     158:          /// <summary>
     159:          /// 属性类型枚举
     160:          /// </summary>
     161:          public enum AttributeEnum
     162:          {
     163:              /// <summary>
     164:              /// 输入框
     165:              /// </summary>
     166:              Text,
     167:              /// <summary>
     168:              /// 下拉框
     169:              /// </summary>
     170:              Select,
     171:              /// <summary>
     172:              /// 单选框
     173:              /// </summary>
     174:              Radio,
     175:              /// <summary>
     176:              /// 复选框
     177:              /// </summary>
     178:              CheckBox
     179:          }
     180:          #endregion
     181:   
     182:          #region JS提示============================================
     183:   
     184:          /// <summary>
     185:          /// 添加编辑删除提示
     186:          /// </summary>
     187:          /// <param name="msgtitle">提示文字</param>
     188:          /// <param name="url">返回地址</param>
     189:          /// <param name="msgcss">CSS样式</param>
     190:          protected void JscriptMsg(string msgtitle, string url, string msgcss)
     191:          {
     192:              string msbox = "parent.jsprint(\"" + msgtitle + "\", \"" + url + "\", \"" + msgcss + "\")";
     193:              ClientScript.RegisterClientScriptBlock(Page.GetType(), "JsPrint", msbox, true);
     194:          }
     195:   
     196:          /// <summary>
     197:          /// 带回传函数的添加编辑删除提示
     198:          /// </summary>
     199:          /// <param name="msgtitle">提示文字</param>
     200:          /// <param name="url">返回地址</param>
     201:          /// <param name="msgcss">CSS样式</param>
     202:          /// <param name="callback">JS回调函数</param>
     203:          protected void JscriptMsg(string msgtitle, string url, string msgcss, string callback)
     204:          {
     205:              string msbox = "parent.jsprint(\"" + msgtitle + "\", \"" + url + "\", \"" + msgcss + "\", " + callback + ")";
     206:              ClientScript.RegisterClientScriptBlock(Page.GetType(), "JsPrint", msbox, true);
     207:          }
     208:          #endregion
     209:   
     210:      }
     211:  }

    在子类校验的时候继承ManagePage的基类,然后就这样校验:

    image

    可以看到这种是通常的设计方案,基类定义,子类校验,不过这个启航动力CMS,他完全是在基类定义枚举,控制仅仅停留在增删改查,浏览,这些,不过CMS确实这一层就可以了,而且它的设计感觉不太好,因为到处都是验证代码,每一个增删改查方法都有这些验证的代码,如果是我我就会用委托的方式绑定方法,在Page_Load里面验证权限,委托绑定增删改查方法,这样,把验证的过程大大节省,这些甚至可以设计成公共的方法,来实现.

    我们今天讲解的是MVC里面的权限验证,MVC天然的Controller,Action,让我们的权限控制更加容易,而且更简洁,更清晰.

    首先,先来看看,MVC里面的一个小特色设计:

    image

    这个是一个普通的model,在mvc示例项目中,他采用Attribute方式来验证,我当时看到的时候感觉耳目一新,以前看<<CLR VIA C#>> Attribute的时候,当时还在想这些东西可以干什么??仅仅是元数据描述??后来才发现,这东西太强大了,控件的设计,反射,ORM,无处不在,Attributes也让代码更加优雅.

    我们可以在mvc中定义各种Attribute来让我们的代码更优雅,而且让权限更简洁,比如我们经常会设计,

      xxxx页面登录后才能访问,

      xxxxx页面匿名用户也能访问,

      xxxx页面必须经过权限验证才能访问,

      xxxxx各种类型

    我们可以定义各种Attribute来描述它,这种描述也让权限控制更加优雅.

    比如:我们有几个登录页面,错误显示页面等等,这些页面,可以单独设计一个Attribute标记来标识.

    image

    我们可以定义各种各样的标记来描述权限控制,

    image

    image

    image

    image

    可以看到我们在这里只需要标记匿名标记,然后在权限拦截中进行处理,如果存在Anonymous标记就默认允许.

    image

    这里在公共基类中设计验证标记,子类继承,这样,我们就可以达到子类全部都需要验证处理..

    接下来,我们就看看,我们的权限拦截如何处理的.

    我们的权限拦截是通过继承ActionFilterAttribute,自定义拦截器,这里参考传说中弦哥的思路.

    简单地说,ActionFilter就是Action过滤器,任何一个请求都像筛子一样的过滤.所以,这个Filter就是筛子,我们需要的就是在这个筛子上做权限控制,这样我们的权限不就容易得多了么?

    这时候,我想到了以前的一张asp.net生命周期,一个请求过来同样经过了HttpModule等一层层,在那里做权限拦截,可能效果更好,如果webform设计,可能要尝试一下看看能不能这么做.

       1:    /// <summary>
       2:      /// 权限拦截
       3:      /// </summary>
       4:      [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
       5:      public class PermissionFilterAttribute : ActionFilterAttribute
       6:      {
       7:          /// <summary>
       8:          /// 权限拦截
       9:          /// </summary>
      10:          /// <param name="filterContext"></param>
      11:          public override void OnActionExecuting(ActionExecutingContext filterContext)
      12:          {
      13:              //权限拦截是否忽略
      14:              bool IsIgnored = false;
      15:              if (filterContext == null)
      16:              {
      17:                  throw new ArgumentNullException("filterContext");
      18:              }
      19:              var path = filterContext.HttpContext.Request.Path.ToLower();
      20:              //获取当前配置保存起来的允许页面
      21:              IList<string> allowPages = ConfigSettings.GetAllAllowPage();
      22:              foreach (string page in allowPages)
      23:              {
      24:                  if (page.ToLower() == path)
      25:                  {
      26:                      IsIgnored = true;
      27:                      break;
      28:                  }
      29:              }
      30:              if (IsIgnored)
      31:                  return;
      32:              //接下来进行权限拦截与验证
      33:              object[] attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(ViewPageAttribute), true);
      34:              var isViewPage = attrs.Length == 1;//当前Action请求是否为具体的功能页
      35:   
      36:              if (this.AuthorizeCore(filterContext) == false)//根据验证判断进行处理
      37:              {
      38:                  //注:如果未登录直接在URL输入功能权限地址提示不是很友好;如果登录后输入未维护的功能权限地址,那么也可以访问,这个可能会有安全问题
      39:                  if (isViewPage == true)
      40:                  {
      41:                      //跳转到登录页面
      42:                      filterContext.RequestContext.HttpContext.Response.Redirect("~/Admin/Manage/UserLogin");
      43:                  }
      44:                  else
      45:                  {
      46:   
      47:                      //跳转到登录页面
      48:                      filterContext.RequestContext.HttpContext.Response.Redirect("~/Admin/Manage/Error");
      49:                  }
      50:              }
      51:          }

    这个Attribute直接借鉴的弦哥的模型,

    这样我们可以对程序进行细化的处理过程.

    针对不同的标记进行处理:

       1:    /// <summary>
       2:          /// [Anonymous标记]验证是否匿名访问
       3:          /// </summary>
       4:          /// <param name="filterContext"></param>
       5:          /// <returns></returns>
       6:          public bool CheckAnonymous(ActionExecutingContext filterContext)
       7:          {
       8:              //验证是否是匿名访问的Action
       9:              object[] attrsAnonymous = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AnonymousAttribute), true);
      10:              //是否是Anonymous
      11:              var Anonymous = attrsAnonymous.Length == 1;
      12:              return Anonymous;
      13:          }
      14:          /// <summary>
      15:          /// [LoginAllowView标记]验证是否登录就可以访问(如果已经登陆,那么不对于标识了LoginAllowView的方法就不需要验证了)
      16:          /// </summary>
      17:          /// <param name="filterContext"></param>
      18:          /// <returns></returns>
      19:          public bool CheckLoginAllowView(ActionExecutingContext filterContext)
      20:          {
      21:              //在这里允许一种情况,如果已经登陆,那么不对于标识了LoginAllowView的方法就不需要验证了
      22:              object[] attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(LoginAllowViewAttribute), true);
      23:              //是否是LoginAllowView
      24:              var ViewMethod = attrs.Length == 1;
      25:              return ViewMethod;
      26:          }
      27:   
      28:          /// <summary>
      29:          /// //权限判断业务逻辑
      30:          /// </summary>
      31:          /// <param name="filterContext"></param>
      32:          /// <param name="isViewPage">是否是页面</param>
      33:          /// <returns></returns>
      34:          protected virtual bool AuthorizeCore(ActionExecutingContext filterContext)
      35:          {
      36:   
      37:              if (filterContext.HttpContext == null)
      38:              {
      39:                  throw new ArgumentNullException("httpContext");
      40:              }
      41:              //验证当前Action是否是匿名访问Action
      42:              if (CheckAnonymous(filterContext))
      43:                  return true;
      44:              //未登录验证
      45:              if (SessionHelper.Get("UserID") == null)
      46:              {
      47:                  return false;
      48:              }
      49:              //验证当前Action是否是登录就可以访问的Action
      50:              if (CheckLoginAllowView(filterContext))
      51:                  return true;
      52:   
      53:              //下面开始用户权限验证
      54:              var user = new UserService();
      55:              SysCurrentUser CurrentUser = new SysCurrentUser();
      56:              var controllerName = filterContext.RouteData.Values["controller"].ToString();
      57:              var actionName = filterContext.RouteData.Values["action"].ToString();
      58:              //如果是超级管理员,直接允许
      59:              if (CurrentUser.UserID == ConfigSettings.GetAdminUserID())
      60:              {
      61:                  return true;
      62:              }
      63:              //如果拥有超级管理员的角色就默认全部允许
      64:              string AdminUserRoleID = ConfigSettings.GetAdminUserRoleID().ToString();
      65:              //检查当前角色组有没有超级角色
      66:              if (Tools.CheckStringHasValue(CurrentUser.UserRoles, ',', CurrentUser.UserRoles))
      67:              {
      68:                  return true;
      69:              }
      70:   
      71:              //Action权限验证
      72:              if (controllerName.ToLower() != "manage")//如果当前Action请求为具体的功能页并且不是Manage中 Index页和Welcome页
      73:              {
      74:                  //验证
      75:                  if (!user.RoleHasOperatePermission(CurrentUser.UserRoles, controllerName, actionName))//如果验证该操作是否拥有权限
      76:                  {
      77:                      return false;
      78:                  }
      79:              }
      80:              //管理页面直接允许
      81:              return true;
      82:          }

    可以看到我们仅仅这一个PermissionAttribute配合其他的Attribute就实现了权限的拦截控制.

    当然,我们仍然需要配置那些东西?

    过滤页面.....

    有一些页面我们可以直接配置允许访问的页面:

       1:    var path = filterContext.HttpContext.Request.Path.ToLower();
       2:              //获取当前配置保存起来的允许页面
       3:              IList<string> allowPages = ConfigSettings.GetAllAllowPage();
       4:              foreach (string page in allowPages)
       5:              {
       6:                  if (page.ToLower() == path)
       7:                  {
       8:                      IsIgnored = true;
       9:                      break;
      10:                  }
      11:              }
      12:              if (IsIgnored)
      13:                  return;

    image

    我们在自定义配置文件中,可以定义允许访问的页面,比如:错误页之类的,可能有些人觉得,不需要,但是这个配置是在程序发布以后,仍然能够很轻松的进行配置,所以,预留一个配置页面还是蛮有必要的.

    image

    image

    同时我们也需要配置超级管理员身份和角色....

    有人觉得,这些需要么?

    我觉得是需要的,因为数据库读取出来的角色,根本没办法分辨超级管理员,只能数据库动态配置,我们就预定义这样的一个超级管理员角色的身份ID,让这个超级管理角色拥有任何的功能和任何的权限,甚至读取数据库的时候,都是读取的所有模块权限,菜单权限.

    这样我们的配置工作就非常简单了,特别是数据库没有大部分配置初试信息(比如菜单信息,角色信息,)的时候,我们不需要手动往数据库添加数据,直接在程序中添加就可以了,也算是一个超级管理员身份.

    接下来,我们的权限控制基本上就差不多了,现在我们可以安心的写页面了,权限神马东西,跟咱关系就不大了,这样,分工不是更爽,干别人的活才是最纠结的.......

    接下来,我们可以继续设计一些公共类来简化我们日常的操作,对于公共类的设计,我觉得要拿出最大的热情与态度,要知道这些是能够真正节省我们时间的东西.

    只有设计好它,我们以后才会更快更爽更轻松.

    我们经常会遇到这样的代码:

       1:    /// <summary>
       2:      /// 保存资料业务
       3:      /// </summary>
       4:      /// <param name="context"></param>
       5:      public void SaveCompany(HttpContext context)
       6:      {
       7:          //用户json数据读取
       8:          company Info=new company ();
       9:          String CompanyStr = context.Request["Company"];
      10:          string id=context.Request["id"];
      11:          string pic = context.Request["pic"];
      12:          if (!Tools.IsValidInput(ref pic, true) || !Tools.IsValidInput(ref id, true))
      13:          {
      14:              return;
      15:          }
      16:        //图片保存
      17:          //System.IO.StreamWriter sw = new System.IO.StreamWriter(context.Server.MapPath("tzt.txt"), true);
      18:          //sw.Write(CompanyStr);
      19:          //sw.Close();
      20:          //使用Newtonsoft.Json.dll组件解析json对象
      21:       
      22:          JObject o = JObject.Parse(CompanyStr);
      23:          Info.Username = (string)o.SelectToken("Username");
      24:          if (!new companyBLL().CheckExistUserName(Info.Username))
      25:          {
      26:              context.Response.Write(false);
      27:              return;
      28:          }
      29:          Info.Password = (string)o.SelectToken("Password");
      30:          Info.Name = (string)o.SelectToken("Name");
      31:          Info.Isrecommend = ((string)o.SelectToken("Isrecommend"))=="true" ? "1" : "0";
      32:          Info.Fac = (string)o.SelectToken("Fac");
      33:          Info.Representative = (string)o.SelectToken("Representative");
      34:          Info.Isshow = ((string)o.SelectToken("Isshow")) == "true" ? "1" : "0";
      35:          Info.State = ((string)o.SelectToken("State")) == "true" ? "1" : "0";
      36:          Info.State1 = ((string)o.SelectToken("State1")) == "true" ? "1" : "0";
      37:         
      38:          Info.Zipcode = (string)o.SelectToken("Zipcode");
      39:          Info.QQ = (string)o.SelectToken("QQ");
      40:          Info.Telephone = (string)o.SelectToken("Telephone");
      41:          Info.mobilephone = (string)o.SelectToken("mobilephone");
      42:          Info.Email = (string)o.SelectToken("Email");
      43:          Info.Address = (string)o.SelectToken("Address");
      44:          Info.Website = (string)o.SelectToken("Website");
      45:          Info.Award = (string)o.SelectToken("Award");
      46:          Info.Introduction = (string)o.SelectToken("Introduction");
      47:          Info.Picturepath = pic;
      48:   
      49:          if (!string.IsNullOrEmpty(id))
      50:              Info.Id = Convert.ToInt32(id);
      51:   
      52:          if (!Info.Id.HasValue)
      53:          {
      54:              Info.rank = 0;
      55:              Info.hit = 0;
      56:              //执行增加操作
      57:              new companyBLL().AddNew(Info);
      58:              SMTP smtp = new SMTP(Info.Email);
      59:              string webpath = context.Request.Url.Scheme + "://" + context.Request.Url.Authority + System.Web.VirtualPathUtility.ToAbsolute("~/Default.aspx");
      60:              smtp.Activation(webpath, Info.Name);//发送激活邮件
      61:          }
      62:          else
      63:          {
      64:              new companyBLL().Update(Info);
      65:          }
      66:   
      67:   
      68:      }

    这是我以前一个电子商务网站项目写的,

    我现在看,简直到处都是毛病.......

    首先,关于form读取内容占了一大块.......

    可以想象,到处都是赋值语句,看到都吐血,再加上一些验证非空,验证函数等等,更是罪加一等的恶劣.

    当然我们需要一步一步的解决这些问题,首先是剥离关于表单读取的内容,封装到一个类中,然后在类中进行验证处理.

    权限验证中的样例,

    image

    image

    验证也没有做大块的处理,不过大家可以注意,可以看到想当的简洁,我们同时需要各种辅助类的设计,强制转化的处理,非空验证的处理,等等,我们直接设计成扩展方法就能达到上图中ObjToIntNULL()的形式, 也不需要ConvertToInt32(xxxxx)的形式来转化了,不是更简洁么?

       1:  /*  作者:       tianzh
       2:  *  创建时间:   2012/7/22 15:38:20
       3:  *
       4:  */
       5:  using System;
       6:  using System.Collections.Generic;
       7:  using System.Linq;
       8:  using System.Text;
       9:   
      10:  namespace TZHSWEET.Common
      11:  {
      12:      /// <summary>
      13:      /// 强制转化辅助类(无异常抛出)
      14:      /// </summary>
      15:      public static class ConvertHelper
      16:      {
      17:          #region 强制转化
      18:          /// <summary>
      19:          /// object转化为Bool类型
      20:          /// </summary>
      21:          /// <param name="obj"></param>
      22:          /// <returns></returns>
      23:          public static bool ObjToBool(this object obj)
      24:          {
      25:              bool flag;
      26:              if (obj == null)
      27:              {
      28:                  return false;
      29:              }
      30:              if (obj.Equals(DBNull.Value))
      31:              {
      32:                  return false;
      33:              }
      34:              return (bool.TryParse(obj.ToString(), out flag) && flag);
      35:          }
      36:          /// <summary>
      37:          /// object强制转化为DateTime类型(吃掉异常)
      38:          /// </summary>
      39:          /// <param name="obj"></param>
      40:          /// <returns></returns>
      41:          public static DateTime? ObjToDateNull(this object obj)
      42:          {
      43:              if (obj == null)
      44:              {
      45:                  return null;
      46:              }
      47:              try
      48:              {
      49:                  return new DateTime?(Convert.ToDateTime(obj));
      50:              }
      51:              catch (ArgumentNullException ex)
      52:              {
      53:                  return null;
      54:              }
      55:          }
      56:          /// <summary>
      57:          /// int强制转化
      58:          /// </summary>
      59:          /// <param name="obj"></param>
      60:          /// <returns></returns>
      61:          public static int ObjToInt(this object obj)
      62:          {
      63:              if (obj != null)
      64:              {
      65:                  int num;
      66:                  if (obj.Equals(DBNull.Value))
      67:                  {
      68:                      return 0;
      69:                  }
      70:                  if (int.TryParse(obj.ToString(), out num))
      71:                  {
      72:                      return num;
      73:                  }
      74:              }
      75:              return 0;
      76:          }
      77:          /// <summary>
      78:          /// 强制转化为long
      79:          /// </summary>
      80:          /// <param name="obj"></param>
      81:          /// <returns></returns>
      82:          public static long ObjToLong(this object obj)
      83:          {
      84:              if (obj != null)
      85:              {
      86:                  long num;
      87:                  if (obj.Equals(DBNull.Value))
      88:                  {
      89:                      return 0;
      90:                  }
      91:                  if (long.TryParse(obj.ToString(), out num))
      92:                  {
      93:                      return num;
      94:                  }
      95:              }
      96:              return 0;
      97:          }
      98:          /// <summary>
      99:          /// 强制转化可空int类型
     100:          /// </summary>
     101:          /// <param name="obj"></param>
     102:          /// <returns></returns>
     103:          public static int? ObjToIntNull(this object obj)
     104:          {
     105:              if (obj == null)
     106:              {
     107:                  return null;
     108:              }
     109:              if (obj.Equals(DBNull.Value))
     110:              {
     111:                  return null;
     112:              }
     113:              return new int?(ObjToInt(obj));
     114:          }
     115:          /// <summary>
     116:          /// 强制转化为string
     117:          /// </summary>
     118:          /// <param name="obj"></param>
     119:          /// <returns></returns>
     120:          public static string ObjToStr(this object obj)
     121:          {
     122:              if (obj == null)
     123:              {
     124:                  return "";
     125:              }
     126:              if (obj.Equals(DBNull.Value))
     127:              {
     128:                  return "";
     129:              }
     130:              return Convert.ToString(obj);
     131:          }
     132:          /// <summary>
     133:          /// Decimal转化
     134:          /// </summary>
     135:          /// <param name="obj"></param>
     136:          /// <returns></returns>
     137:          public static decimal ObjToDecimal(this object obj)
     138:          {
     139:              if (obj == null)
     140:              {
     141:                  return 0M;
     142:              }
     143:              if (obj.Equals(DBNull.Value))
     144:              {
     145:                  return 0M;
     146:              }
     147:              try
     148:              {
     149:                  return Convert.ToDecimal(obj);
     150:              }
     151:              catch
     152:              {
     153:                  return 0M;
     154:              }
     155:          }
     156:          /// <summary>
     157:          /// Decimal可空类型转化
     158:          /// </summary>
     159:          /// <param name="obj"></param>
     160:          /// <returns></returns>
     161:          public static decimal? ObjToDecimalNull(this object obj)
     162:          {
     163:              if (obj == null)
     164:              {
     165:                  return null;
     166:              }
     167:              if (obj.Equals(DBNull.Value))
     168:              {
     169:                  return null;
     170:              }
     171:              return new decimal?(ObjToDecimal(obj));
     172:          } 
     173:          #endregion
     174:   
     175:      }
     176:  }

    一些好的常用的扩展方法同样是一个相当大的改进,对于代码,也更清晰,更简洁,我们同时可以设计一些非空验证等等.

       1:    #region 判断对象是否为空
       2:          /// <summary>
       3:          /// 判断对象是否为空,为空返回true
       4:          /// </summary>
       5:          /// <typeparam name="T">要验证的对象的类型</typeparam>
       6:          /// <param name="data">要验证的对象</param>        
       7:          public static bool IsNullOrEmpty<T>(this T data)
       8:          {
       9:              //如果为null
      10:              if (data == null)
      11:              {
      12:                  return true;
      13:              }
      14:   
      15:              //如果为""
      16:              if (data.GetType() == typeof(String))
      17:              {
      18:                  if (string.IsNullOrEmpty(data.ToString().Trim())||data.ToString ()=="")
      19:                  {
      20:                      return true;
      21:                  }
      22:              }
      23:   
      24:              //如果为DBNull
      25:              if (data.GetType() == typeof(DBNull))
      26:              {
      27:                  return true;
      28:              }
      29:   
      30:              //不为空
      31:              return false;
      32:          }
      33:   
      34:          /// <summary>
      35:          /// 判断对象是否为空,为空返回true
      36:          /// </summary>
      37:          /// <param name="data">要验证的对象</param>
      38:          public static bool IsNullOrEmpty(this object data)
      39:          {
      40:              //如果为null
      41:              if (data == null)
      42:              {
      43:                  return true;
      44:              }
      45:   
      46:              //如果为""
      47:              if (data.GetType() == typeof(String))
      48:              {
      49:                  if (string.IsNullOrEmpty(data.ToString().Trim()))
      50:                  {
      51:                      return true;
      52:                  }
      53:              }
      54:   
      55:              //如果为DBNull
      56:              if (data.GetType() == typeof(DBNull))
      57:              {
      58:                  return true;
      59:              }
      60:   
      61:              //不为空
      62:              return false;
      63:          }
      64:          #endregion

    这些东西其实真没有太多难的东西,只是简单的为了追求更简洁更方便而已,磨刀不误砍柴工就是这个道理,思考怎么偷懒才是程序员应该干的事情,不管多么忙都要停下来思考,想想怎么样才能偷懒!

    image

    界面上,不太会美工,直接照搬的LigerUI界面!

    目前进度已经完成的差不多了,接下来要陆续总结学到的经验与技巧!

    我的google code开源网站首页:http://code.google.com/p/tzhsweetsourse/ 一直在努力,从未曾放弃,努力学习中..... 追逐吧!奔跑的少年! 拼搏吧!勇敢的心! 有梦想,就有希望! 为梦想而不懈奋斗着!
  • 相关阅读:
    14.4.9 Configuring Spin Lock Polling 配置Spin lock 轮询:
    14.4.8 Configuring the InnoDB Master Thread IO Rate 配置InnoDB Master Thread I/O Rate
    14.4.7 Configuring the Number of Background InnoDB IO Threads 配置 后台InnoDB IO Threads的数量
    14.4.7 Configuring the Number of Background InnoDB IO Threads 配置 后台InnoDB IO Threads的数量
    14.4.6 Configuring Thread Concurrency for InnoDB 配置Thread 并发
    14.4.6 Configuring Thread Concurrency for InnoDB 配置Thread 并发
    14.4.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering
    14.4.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering
    14.4.4 Configuring the Memory Allocator for InnoDB InnoDB 配置内存分配器
    14.4.4 Configuring the Memory Allocator for InnoDB InnoDB 配置内存分配器
  • 原文地址:https://www.cnblogs.com/fcsh820/p/2804611.html
Copyright © 2011-2022 走看看