c#特性详解【含常用过滤器实例】

基础拾遗

基础拾遗------特性详解

基础拾遗------webservice详解

基础拾遗------redis详解

基础拾遗------反射详解

基础拾遗------委托详解

基础拾遗------接口详解

基础拾遗------泛型详解

前言

  本来7月份想着是用一个月把基础拾遗写完的,结果断断续续写了4个月了,才写了这几篇,这两天又规划着多写几篇,希望能坚持吧。两天一次和同事聊天竟然好多人都不知道,他们每天却都在用。

1.特性概念

  特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。

特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。比如我们在执行方法之前,要先判断一下用户有没有执行这个方法的权限,方法出现异常的时候怎么去处理。

1.1.枚举

  为啥要在这聊枚举,是不是sa,我把代码贴出来。

 enum Fruit
    {
        [Description("苹果")]
        Apple,
        [Description("橙子")]
        Orange,
        [Description("西瓜")]
        Watermelon
    }

Ok,你只需要F12 Description 会看到

public DescriptionAttribute(string description);

  这个家伙,没错DescriptionAttribute(string description),它就是一个特性。现在知道了吧你其实也在用到特性,只是你知不到而已。这个开篇和以往不一样,并且废话有点多。尴尬了,现在回来。

2.预定义特性

  注:1.特性大致分为两种特性预定义特性和定制特性。

    2.预定义特性.Net 框架提供了三种预定义特性:

2.1.AttributeUsage(AttributeUsageAttribute 类):

  2.1.1.作用:

  描述了如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。

  2.1.2.使用:

   [AttributeUsage(validon, AllowMultiple = false, Inherited = true)]

  //限定特性类的应用范围  (这里规定ClassMsg这个特性类只能用于类和字段)
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
    //定制MsgAttribute特性类,继承于Attribute
    public class ClassMsgAttribute : Attribute
    {
        //定义_msg字段和Msg属性//Msg属性用于读写msg字段
        string _msg;
        public string Msg { get { return _msg; } set { _msg = value; } }
        public ClassMsgAttribute() { }
        //重载构造函数接收一个参数,赋值给_msg字段
        public ClassMsgAttribute(string s) { _msg = s; }
    }
  //调用
    //在Person类上标记ClassMsg特性
    [ClassMsg(Msg = "这是关于人的姓名信息的类")]
    class Person
    {
        //在_name字段上应用ClassMsg特性
        [ClassMsg("这是存储姓名的字段")]
        string _name;
        //以下特性无法应用,因为MsgAttribute定义的特性只能用于类和字段
        //[ClassMsg("这是读写姓名字段的属性")]
        public string Name { get { return _name; } set { _name = value; } }
    }    

} 

以上是AttributeUsage使用时的一个小栗子。

2.1.3.AttributeUsage 参数说明
  validon:被放置的语言元素,它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All

  AllowMultiple:该值指示能否为一个程序元素指定多个指示属性实例。如果允许指定多个实例,则为 true;否则为 false。默认为 false。

  Inherited:该值指示指示的属性能否由派生类和重写成员继承。如果该属性可由派生类和重写成员继承,则为 true,否则为 false。默认为 true。

2.2.Obsolete(ObsoleteAttribute 类):

2.2.1.作用:

  这个单词是废弃的意思,其实这个特性也是用来 就是舍弃这个方法,生成一个错误或警告。

2.2.2.用法:

  [Obsolete( message, iserror)]

 [Obsolete("这个方法不在用来", true)]
   static void OldMethod()
   {
      Console.WriteLine("不执行的");
   }

2.2.3.Obsolete参数说明

  message:告诉你为什么废弃它

  iserror,是一个布尔值。如果该值为 true,编译器应把该项目的使用当作一个错误。默认值是 false(编译器生成一个警告)

2.3.Conditional(ConditionalAttribute 类)

2.3.1.作用: 

  据预处理标识符执行方法;至于预处理器指令,就需要大家自己去了解了。

2.3.2.用法

   [Conditional( conditionalSymbol)]

由于我不了解c#预处理器指令,所以这个真的不会用,所以就不往下写了等我了解了预处理器指令再补上吧。

3.定制特性

3.1.定制特性

  定制特性:利用定制特性可以宣告自己的代码构造添加注释来实现特殊功能。它允许允许几乎每个元数据表记录项定义和应用信息。这种可扩展的元数据信息能在运行时查询,从而动态改变代码的执行方式。使用各种net framework技术会发现他们都利用了地址特性。目的是为了方便开发者在代码中表达他们的意图。

3.2.使用定制特性

  .net framework类库(fcl)中定义了几百个类库,可以将它们用到自己代码中的各种元素。

举几个小栗子:

3.2.1.Description:开篇我们就说枚举这个家伙,是的Description它就是框架中用来定义枚举的一个定制特性。它的定义如下:

[AttributeUsage(AttributeTargets.Field,AllowMultiple =true,Inherited = true)]
  class DescriptionAttribute:Attribute
  {
      private string description;
      public  string Description
      {
          get { return description; }
      }  

      public  DescriptionAttribute(String description)
      {
          this.description = description;
      }
  }

AttributeTargets.Field:表示此特性只用于字段;DescriptionAttribute(String description) 他的构造函数有一个参数用来进行性字段描述,我们在操作枚举的时候可以让这个描述现在在我们的页面上,想想那些还在用字典关联的做法是不是这种更方便呢?



 enum Fruit
    {
        [Description("苹果")]
        Apple,
        [Description("橙子")]
        Orange,
        [Description("西瓜")]
        Watermelon
    }

  Flags:用于枚举类型,枚举类型就成为了位标志(big flag)集合。

  Seriaklizable:用与类型,告诉序列化器一个是空的字段可以序列化和反序列化。

  dllimport:用于方法,告诉clr该方法的实现位于指定dll的非托管代码中。

有很多,大家应该都会用得到,在i这大家知道net框架类库中有很多可用的定制特性即可,用的时候多总结慢慢就熟悉了。

3.2.定义自定义特性类

上面写了一大通说特性怎么怎么样,最后根据我们自己的需要定义自己的特性,应该是我们更高一些的需求,其实看net框架中的代码,我们写出自己定义的特性应该很容易。

创建并使用自定义特性包含四个步骤:

3.2.1.声明自定义特性



[AttributeUsage(AttributeTargets.Class |AttributeTargets.Constructor |AttributeTargets.Field |AttributeTargets.Method |AttributeTargets.Property,AllowMultiple = true)]
public class FlagInfoAttribute : System.Attribute

注:上面介绍过预定义特性所以也就没什么可讲的,大家应该知道attributeUsage定义的意思吧。所有的特性都是继承system.attribute这个在这强调一下。

3.2.2.构建自定义特性

[AttributeUsage(AttributeTargets.Class |AttributeTargets.Constructor |AttributeTargets.Field |AttributeTargets.Method |AttributeTargets.Property,AllowMultiple = true)]
public class FlagInfoAttribute : System.Attribute
{
string flagInfo="";
bool run=false;
public FlagInfoAttribute ()
{

}
public FlagInfoAttribute (string flagInfo,bool run) { flaginfo=flaginfo; run=dosp; } public FlagInfoAttribute (string flagInfo) { flaginfo=flaginfo; } }

构造自定义特性其实和我们定义类基本一致,传参只需在构造函数中定义即可。

3.2.3.在目标程序元素上应用自定义特性

特性的使用在方法上面“【】”标记使用即可



[flaginfo("测试用力",true)]
piblic class falgDemo()

就是这么简单,你是不是了解了特性这个知识点,应该是了解了,但是它是不是还可以更吊一些,前言我说过他叫过滤器,是的过滤器,只有了解到它过滤器的功能你才能真的发现它的厉害。

4.过滤器(Filter)

其实这一块我在通过过滤器实现性能监控(含源码)有用到,只是没进行讲解这个知识点而已。

过滤器的使用让我们在代码运行时的时候对其进行Action运行前,运行后和异常时进行可控性控制。至于例子看上面的博客就行。它解决了我在项目中一个难题,代码很简单,思路很不错。

4.1.授权过滤器(Authorize)

4.1.1.默认授权过滤器Authorize

现在在网上无论是要求身份验证的地方多得是,发邮件,买东西,在博客中下载资源。这里的某些操作,就是要经过验证授权才被允许。在MVC中可以利用Authorize来实现。

 [Authorize]
 public ActionResult Login()
  {
      return View();
  }

如果使用此过滤器不得到认证,就算路由配置正确也是返回404错误。

4.1.2.自定义过滤器(继承AuthorizeAttribute)

需要重写底下两个方法:

bool AuthorizeCore(HttpContextBase httpContext):这里主要是授权验证的逻辑处理,返回true的则是通过授权,返回了false则不是。

void HandleUnauthorizedRequest(AuthorizationContext filterContext):这个方法是处理授权失败的事情

 public class MyAuthorizeAttribute:AuthorizeAttribute
    {

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
        bool flag=false;
        //逻辑验证
         return flag;
        }
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.HttpContext.Response.Redirect("/Customer/Login");
        }
    }        
      [MyAuthorize]
        public ActionResult show()
        {
            return View();
        }

以上代码经常用,很少用默认的。

4.2.处理错误过滤器(HandleError)

处理异常,是不是你第一个想到的是try  catch,那么你就要在这里稍微换下思路了,因为有异常不一定就抛出,就算抛出是不是有一个专门的处理页面显示是不是更好一些。

4.2.1.默认HandleError

1.在使用此过滤器的时候,当有错误的时候他会默认跳转到Views/Shared/Error视图。

2.还要到web.config文件中的<system.web>一节中添加以下代码

<customErrors mode="On" />
 [HandleError(ExceptionType = typeof(Exception))]
 public ActionResult ThrowErrorLogin()
 {
     throw new Exception("发生了错误,亲");
 }

其中ExceptionType要处理的异常的类型,相当于Try/Catch语句块里Catch捕捉的类型。

它的参数属性还有:(F12查看即可)

View:指定需要展示异常信息的视图,只需要视图名称就可以了,这个视图文件要放在Views/Shared文件夹里面

Master:指定要使用的母版视图的名称

Order:指定过滤器被应用的顺序

4.2.2自定义错误异常处理(继承HandleErrorAttribute)

要重写的方法void OnException(ExceptionContext filterContext)

对象ExceptionContext它的属性:

ActionDescriptor:提供详细的操作方法

Result:提供详细的操作方法

Exception:未处理的异常

ExceptionHandled:如果这个异常处理完的话,就把它设为true,那么即使有其他的错误处理器捕获到这个异常,也可以通过ExceptionHandler属性判断这个异常是否经过了处理,以免重复处理一个异常错误而引发新的问题。

4.3.缓存过滤器(OutputCache)

OutputCache过滤器用作缓存,节省用户访问应用程序的时间和资源,以提高用户体验。一般我都是直接做缓存处理,不怎么用这个过滤器。

4.4.自定义过滤器

OnActionExecuting执行前,OnActionExecuted执行后,OnResultExecuting返回结果前,OnResultExecuted返回方法后。

可以说自定义过滤器让我们对我们方法整体进行时有了很好的控制的得到了保证。

public class MyCustomerFilterAttribute : ActionFilterAttribute
    {
      public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            filterContext.HttpContext.Response.Write(string.Format( "<br/>  Action finish Execute....."));
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            CheckMessage(filterContext);
            filterContext.HttpContext.Response.Write(string.Format("<br/> Action start Execute....."));
            base.OnActionExecuting(filterContext);
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write(string.Format("<br/>  Action finish Result....."));
            base.OnResultExecuted(filterContext);
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Write(string.Format("<br/>  Action start Execute....."));
            base.OnResultExecuting(filterContext);
        }

    }

运用

 [MyCustomerFilter]
        public ActionResult CustomerFilterTest()
        {
            Response.Write("<br/>正式方法执行");
            return View();
        }

运行一下看一下数序,这个在你理解后,我敢保证它将是你解决问题时一个全新的思路。

时间: 2024-10-27 10:42:43

c#特性详解【含常用过滤器实例】的相关文章

iOS开发——高级特性&amp;Runtime运行时特性详解

Runtime运行时特性详解 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的动态特性,使这门古老的语言焕发生机.主要内容如下: 引言 简介 与Runtime交互 Runtime术语 消息 动态方法解析 消息转发 健壮的实例变量(Non Fragile ivars) Objective-C Associated Objects Method Swizzling 总结 引言 曾经觉得Objc特别方便上手,面对着 Cocoa 中大量

Servlet 3.0 新特性详解

转自:https://www.ibm.com/developerworks/cn/java/j-lo-servlet30/ Servlet 3.0 新特性详解 张 建平2010 年 4 月 23 日发布 WeiboGoogle+用电子邮件发送本页面 6 Servlet 3.0 新特性概述 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布.该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署.其

开启 J2EE(六)— Servlet之Filter详解及乱码处理实例

定义和功能 Filter:过滤器,它能够在request到达Servlet之前预处理request,也可以在离开Servlet时处理response,通过对request或response的处理已达到过滤功能.但是Filter只是对request和response请求进行了拦截处理,通常不产生请求或者响应. 实现的接口 我们写Servlet需要继承一个类,Filter也一样,要实现一个接口(扩展性的体现啊):javax.servlet.Filter,并实现该接口的三个方法: <span styl

Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验

Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 这一章很多,但是很有趣,也是这书的最后一章知识点了,我现在还在考虑要不要写这个拼图和2048的案例,在此之前,我们先来玩玩Android5.X的新特性吧!

IOS---UICOLLECTIONVIEW详解和常用API翻译

IOS---UICOLLECTIONVIEW详解和常用API翻译 UICollectionView 1.必须要设置布局参数 2.注册cell 用法类似于UITableView 类.自动实现重用,必须注册初始化. 使用UICollectionView必须实现UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout这三个协议. Collection View的构成,我们能看到的有三个部

C#中的 特性 详解(转载)

本篇幅转载于:http://www.cnblogs.com/rohelm/archive/2012/04/19/2456088.html C#中特性详解 特性提供了功能强大的方法,用于将元数据或声明信息与代码(程序集.类型.方法.属性等)相关联.特性与程序实体关联后,即可在运行时使用"反射"的技术查询特性. 特性具有以下属性: 特性可向程序中添加元数据.元数据是有关在程序中定义的类型的信息.所有的 .NET 程序集都包含指定的一组元数据,这些元数据描述在程序集中定义的类型和类型成员.可

【转】C#各个版本中的新增特性详解

转自:http://www.cnblogs.com/knowledgesea/p/6694979.html 序言 自从2000年初期发布以来,c#编程语言不断的得到改进,使我们能够更加清晰的编写代码,也更加容易维护我们的代码,增强的功能已经从1.0搞到啦7.0甚至7.1,每一次改过都伴随着.NET Framework库的相应支持,也不断的带给我们期待与惊喜.下面我们就对c#一路走到现在,做一个回顾与学习. C#语言目标与前行 c#的设计目标是有以下几点: 旨在是一种简单,现代,通用的面向对象编程

Mysql 三大特性详解

Mysql 三大特性详解 Mysql Innodb后台线程 工作方式 首先Mysql进程模型是单进程多线程的.所以我们通过ps查找mysqld进程是只有一个. 体系架构 InnoDB存储引擎的架构如下图所以,是由多个内存块组成的内存池,同时又多个后台线程进行工作,文件是存储磁盘上的数据. 后台线程 上面看到一共有四种后台线程,每种线程都在不停地做自己的工作,他们的分工如下: Master Thread: 是最核心的线程,主要负责将缓冲池中的数据异步刷新的磁盘,保证数据的一致性,包括脏页的刷新.合

Atitit.jdk&#160;java8的语法特性详解&#160;attilax&#160;总结

Atitit.jdk java8的语法特性详解 attilax 总结 1.1. 类型推断这个特别有趣的.鲜为人知的特性1 2. Lambda1 2.1. 内部迭代意味着改由Java类库来进行迭代,而不是客户代码.例如:1 2.2. Stream 流失接口 管道(pipelines)模式2 2.3. 方法引用(Method reference)2 2.4.  默认方法(Default method)2 2.5. 生成器函数(Generator function)2 2.6. 新加入的Nashorn