C#特性

来源:互联网 发布:2016奥运女排数据 编辑:程序博客网 时间:2024/05/18 00:27

<1>

 

C#特性学习笔记

特性标签的本质:
1>特性是一个类,这个类的声明我们有一个规范,即:以Attribute结尾,例如MyClassAttribute 。当着仅仅是一个规范,如果你是在不以Attribute结尾也没关系。
2>这个类一定要继承自Attribute类。只有继承Attribute类,这个类才是一个特性
注意点:比如一个特性类的名称是MyClassAttribute ,当我们在某个类,方法,属性,字段贴这个特性标签的时候,可以省略它后面的Attribute 直接这样贴就可以 ,如:[MyClass]  当然 你也可以写全称,如[MyClassAttribute]

既然[MyClass] 等于 new MyClassAttribute()  那么很多逻辑就在特性的构造函数中去实现。然后再有需要的类或者其成员上打上特性标签

系统自带特性的介绍

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace WebApplication1{    //Attribute 类    //TypeId属性: 当在派生类中实现时,获取该 Attribute 的唯一标识符。    //AttributeUsageAttribute 类   (AttributeUsageAttribute 类是继承自 Attribute 的)    //AttributeUsageAttribute.Inherited 属性:获取或设置一个布尔值,该值指示指示的属性能否由派生类和重写成员继承。如果该属性可由派生类和重写成员继承,则为 true,否则为 false。默认为 true。    //AttributeUsageAttribute.AllowMultiple 属性:获取或设置一个布尔值,该值指示能否为一个程序元素指定多个指示属性实例。如果允许指定多个实例,则为 true;否则为 false。默认为 false。    //AttributeUsageAttribute.ValidOn 属性:获取一组值,这组值标识指示的属性可应用到的程序元素。属性值:一个或多个 AttributeTargets 值。默认为 All。    //注意:对于一个特性类使用Attribute后缀是一个惯例。然而,如果不添加编译器会自动添加匹配。    //限定特性类的应用范围  (这里规定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; }    }    //---------------------调用ClassMsg这个特性---------------------//    //在Person类上标记ClassMsg特性      [ClassMsg(Msg = "这是关于人的姓名信息的类")]    class Person    {        //在_name字段上应用ClassMsg特性          [ClassMsg("这是存储姓名的字段")]        string _name;        //以下特性无法应用,因为MsgAttribute定义的特性只能用于类和字段          //[ClassMsg("这是读写姓名字段的属性")]          public string Name { get { return _name; } set { _name = value; } }    }  }

另外我们在来看看系统自带的一个[Obsolete] 特性,这个特性的作用就是标记某个方法是否已经过时的
例如:
定义一个Pigcs类
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace 特性学习{    public class Pigcs    {        [Obsolete("此方法已经过时,请调用新的方法NewEat()")] //这个Obsolete特性是专门用来告诉用户某些方法或成员已经过时的消息        public string OldEat()        {            return "我是老的方法";        }         public string  NewEat()        {            return "我是新的方法";        }    }}
我们定义了这个Pigcs类,并在它的OldEat()方法上使用了[Obsolete]这个系统特性。看看效果怎么样

我们在来看看微软自带的这个ObsoleteAttribute特性类


自定义特性,及自定义特性的继承

自定义特性的定义

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace 特性学习{    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]    public class VipAttribute : Attribute //自定义一个Vip特性    {    }    public class Vip5Attribute : VipAttribute //此时Vip5Attribute类也是一个特性了。它默认继承了父类的[AttributeUsage(AttributeTargets.Class| AttributeTargets.Method,AllowMultiple=true,Inherited=true)]    {    }    //现在问题来了: Vip5Attribute继承了VipAttribute,因为VipAttribute这个特性只能用于类和方法,那么这个Vip5Attribute也就只能用在类,和方法上面,那假如我们这个Vip5Attribute想用在类和方法和属性上怎么办呢?    //答案很简单,只要在Vip5Attribute这个特性上加系统特性就好了,如下:    //只要在Vip5Attribute类上打上 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method |AttributeTargets.Property] 就可以了。    //特别要注意,如果在子类上不打特性标签,就默认继承父类的特性标签,但是如果在子类上打了特性标签,就等于覆盖了父类的特性标签。    //例如在子类上打: [AttributeUsage(AttributeTargets.Class] 那么它就只能用于类,而不能像父类那样用于方法     //[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method |AttributeTargets.Property, AllowMultiple = true, Inherited = true)]    //public class Vip5Attribute : VipAttribute    //{    //}}

实现一个登陆验证的特性

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.SessionState;namespace 检查登陆验证.Attributes{    [AttributeUsage(AttributeTargets.Class)]  //这个特性只能用于类    public class CheckLoginAttribute : Attribute //定义一个名字叫CheckLoginAttribute 的特性,用户检查用户是否已经登录    {        //我们知道在一个类上打上[CheckLogin] 就等于 new CheckLoginAttribute() 所以我们在这里定义了这个CheckLoginAttribute特性的不带参数的构造函数,在构造函数中判断用户是否已经登录。如果用户未登录,那么就跳到Login.aspx页面        public  CheckLoginAttribute()        {            if (HttpContext.Current.Session["UserName"] == null)            {                HttpContext.Current.Response.Redirect("Login.aspx");            }        }           }}

特性还有其他的用法


定义一个特性
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace 特性学习{    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method|AttributeTargets.Field|AttributeTargets.Property, AllowMultiple = true, Inherited = true)]    public class VipAttribute : Attribute //自定义一个Vip特性    {        string name;        public string Name { get { return name; } }        public VipAttribute(string disName)        {            this.name = disName; //构造函数初始化私有字段name                 }    }}

假如我有两个类。一个是Pig类(猪) 一个是Dog类 (狗)
Pig类
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace 特性学习{    public class Pig    {        [Vip("猪名字")]        public string Name { get; set; }        [Vip("猪年龄")]        public int Age { get; set; }    }}
Dog类
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace 特性学习{    public class Dog    {        [Vip("狗名字")]        public string Name { get; set; }        [Vip("狗年龄")]        public int Age { get; set; }    }}
根据需求,其实实际就是根据类型来获取类型属性上的的特性标签里的参数值 


用法:
首先创建一个WebFrom页面
WebForm1.aspx文件
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="特性学习.WebForm1" %><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>    <title></title></head><body>    <form id="form1" runat="server">    <div>        </div>        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>        <br />        <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>        <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>    </form></body></html>
WebFrom1.aspx.cs文件
using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace 特性学习{    public partial class WebForm1 : System.Web.UI.Page    {        protected void Page_Load(object sender, EventArgs e)        {            /*             Pig p = new Pig();            Type t = p.GetType();            //获取Pig类中的Name属性            PropertyInfo propName = t.GetProperty("Name");            PropertyInfo propAge = t.GetProperty("Age");            //检查Name这个属性上有没有[Vip]这个特性标签            bool bName = propName.IsDefined(typeof(VipAttribute));            bool bAge = propAge.IsDefined(typeof(VipAttribute));            if (bName)            {                //如果Name属性上有[Vip]这个特性标签,那么就获取这个特性标签                Attribute attr = propName.GetCustomAttribute(typeof(VipAttribute));                VipAttribute vip = attr as VipAttribute; //转换一下类型                this.Label1.Text = vip.Name;                           }            if (bAge)            {                //如果Name属性上有[Vip]这个特性标签,那么就获取这个特性标签                Attribute attr = propAge.GetCustomAttribute(typeof(VipAttribute));                VipAttribute vip = attr as VipAttribute; //转换一下类型                this.Label2.Text = vip.Name;            }            */            //----------------------优化一下代码------------------------            Pig pp = new Pig();  //根据类型来获取类型对应的属性特性标记值,如获取这个[VIP(猪名字)]特性标记里的”猪名字“            // Dog pp = new Dog();            Type tt = pp.GetType();            //获取Pig类型的所有属性            PropertyInfo[] pros = tt.GetProperties();            //遍历属性            foreach (var a in pros)            {                //VipAttribute vipattr = a.GetCustomAttribute<VipAttribute>(); //这样写。或者下面的写法                //获取这个属性上的[vip]标签                Attribute attr = a.GetCustomAttribute(typeof(VipAttribute));                //类型转换                VipAttribute vip = attr as VipAttribute;                switch (a.Name)                {                    case "Name": this.Label1.Text = vip.Name; break;                    case "Age": this.Label2.Text = vip.Name; break;                }            }        }    }}





0 0
原创粉丝点击