C#自定義特性實例


元數據,就是C#中封裝的一些類,無法修改.類成員的特性被稱為元數據中的注釋.

1、什么是特性

     (1)屬性與特性的區別

         屬性(Property):屬性是面向對象思想里所說的封裝在類里面的數據字段,Get,Set方法。

         特性(Attribute):  官方解釋:特性是給指定的某一聲明的一則附加的聲明性信息。 允許類似關鍵字的描述聲明。它對程序中的元素進行標注,如類型、字段、方法、屬性等。從.net角度看,特性是一種 類,這些類繼承於System.Attribute類,用於對類、屬性、方法、事件等進行描述,主要用在反射中。但從面向對象的級別看,其實Attribute是類型級別的,而不是對象級別。

         Attributes和.net文件的元素據保存在一起,可以用來向運行時描述你的代碼,或者在程序運行的時候影響程序的行為。

2、特性的應用

    (1).net中特性用來處理多種問題,比如序列化、程序的安全特性、防止即時編譯器對程序代碼進行優化從而代碼容易調試等等。

     定植特性的本質上是一個類的元素上去添加附加信息,並在運行其通過反射得到該附加信息(在使用數據實體對象時經常用到)

    (2)Attribute 作為編譯器的指令時的應用

         Conditional:起條件編譯的作用,只有滿足條件,才允許編譯器對它的代碼進行編譯。一般在程序調試的時候使用

         DllImport: 用來標記費.net的函數,表明該方法在一個外部的DLL中定義。

         Obsolete: 這個屬性用來標記當前的方法已經廢棄,不再使用

       注:Attribute是一個類,因此DllImport也是一個類,Attribute類是在編譯的時候實例化,而不是像通常那樣在運行時實例化。

         CLSCompliant: 保證整個程序集代碼遵守CLS,否則編譯將報錯。

 3、自定義特性

      使用AttributeUsage,來控制如何應用新定義的特性

     [AttributeUsageAttribute(AttributeTargets.All  可以應用到任何元素

      ,AllowMultiple=true, 允許應用多次,我們的定值特性能否被重復放在同一個程序實體前多次。

      ,Inherited=false,不繼承到派生

        )]

      特性也是一個類,必須繼承於System.Attribute類,命名規范為“類名”+Attribute。不管是直接還是間接繼承,都會成為一個特性類,特性類的聲明定義了一種可以放置在聲明之上新的特性。

     public class MyselfAttribute:System.Attribute

4、自定義特性案例
     以下用一個類似於Hibernate中Session的Save()方法效果,自動持久化對象信息到數據庫來說明自定義特性的使用。

(1)建立Dept表

Create Table Dept(  
    deptNo int identity(1,1) primary key,  
    dname nvarchar(10) not null,  
    description nvarchar(100)  
)  
Go  
-- 何問起 hovertree.com 

(2)自定義特性

/**************自定義特性類*****************/  
/// <summary>  
/// 作用:用來說明表名是什么  
/// AttributeUsage:說明特性的目標元素是什么  
/// AttributeTargets.Class:代表目標元素為Class  
/// </summary>  
[AttributeUsage(AttributeTargets.Class)]  
public class TableAttribute : Attribute{  
  
    /// <summary>  
    /// 表名  
    /// </summary>  
    public string TableName { get; set; }  
 
    #region 構造方法,可選的  
  
    public TableAttribute() {    }  
    public TableAttribute(string tableName) {  
        this.TableName = tableName;  
    }   
 
    #endregion  
}  
  
/**************自定義特性類*****************/  
/// <summary>  
/// 作用:說明列是否為自動增長列  
/// </summary>  
[AttributeUsage(AttributeTargets.Property)]  
class IdentityAttribute: Attribute  
{  
    /// <summary>  
    /// true:是; false:否  
    /// </summary>  
    public bool IsIdentity { get; set; }  
}  
  
/****************實體類***************/  
/// <summary>  
/// 有意將類名定義成與表名不一致  
/// 用Table特性來說明實體類對應的表名是什么  
/// </summary>  
[Table(TableName = "Dept")]  
public class Department {  
  
    /// <summary>  
    /// 部門編號,用特性標注為自動增長  
    /// </summary>  
    [Identity(IsIdentity=true)]  
    public int DeptNo { get; set; }  
  
    /// <summary>  
    /// 部門名稱  
    /// </summary>  
    public string Dname { get; set; }  
  
    /// <summary>  
    /// 部門描述  
    /// </summary>  
    public string Description { get; set; }  
  
    public Department( string name, string desc) {  
        Dname = name;  
        Description = desc;  
    }  
}  
  
/****************執行持久化操作類***************/  
/// <summary>  
/// 執行持久化操作類  
/// </summary>  
public class ADOManager {  
  
    /// <summary>  
    /// 將對象的屬性值作為表中對應列的值來添加  
    /// </summary>  
    /// <param name="obj">要添加的對象</param>  
    public int Save(Object obj) {  
        //1.取得類名:代表表名,用到反射  
        string tableName = obj.GetType().Name;  
        //如果類有TableAttribute特性,在采用特性說明的類名  
        TableAttribute attr = Attribute.GetCustomAttribute(obj.GetType(), typeof(TableAttribute)) as TableAttribute;  
        if (attr != null) {//說明類加了Table特性  
            tableName = attr.TableName;//取得表名  
        }  
  
        //sql語句模板:insert into Dept(deptno,dname,description) values('2','','');  
        StringBuilder sql = new StringBuilder("insert into ");  
        sql.Append(tableName);  
        sql.Append(" (");  
  
        //循環對象的屬性名:取得列名  
        foreach (PropertyInfo item in obj.GetType().GetProperties()) {  
            //取得是否有自動增長的特性  
            IdentityAttribute att = Attribute.GetCustomAttribute(item, typeof(IdentityAttribute)) as IdentityAttribute;  
            if (att == null || !att.IsIdentity) {//沒有,則添加列  
                sql.Append(item.Name);  
                sql.Append(",");  
            }  
        }  
        //去除最后一個逗號'  
        sql.Remove(sql.Length - 1, 1);  
        sql.Append(") values(");  
        //循環取出對象的屬性值:為列賦值  
        foreach (PropertyInfo item in obj.GetType().GetProperties()) {  
            //取得是否有自動增長的特性  
            IdentityAttribute att = Attribute.GetCustomAttribute(item, typeof(IdentityAttribute)) as IdentityAttribute;  
            if (att == null) {//沒有,則追加列的值  
                //GetValue():obj代表什么對象,null代表沒有參數  
                sql.Append("'" + item.GetValue(obj, null) + "'");  
                sql.Append(",");  
            }  
        }  
  
        //去除最后一個逗號'  
        sql.Remove(sql.Length - 1, 1);  
        sql.Append(")");  
        //查看完整的sql語句  
        Console.WriteLine(sql.ToString());  
  
        //執行sql語句  
        SqlConnection conn = new SqlConnection("server=.;database=test;integrated security=true");  
        SqlCommand comm = new SqlCommand(sql.ToString(), conn);  
        conn.Open();  
        int r = comm.ExecuteNonQuery();  
        conn.Close();  
  
        return r;//返回執行結果  
    }  
}  
  /* 何問起 hovertree.com */
/****************測試類關鍵代碼***************/  
Department dept = new Department("開發部", "負責產品的研發");  
ADOManager manager = new ADOManager();  
int r = manager.Save(dept);  
  
Console.WriteLine(r==0?"失敗":"成功");  

小結:

C#的特性類和Java中的元注釋一樣

特性其本質就是一個繼承了Attribute的類

使用使可以省略Attribute結尾,如:TableAttribute =>> Table

特性將會影響其作用的目標元素的編譯和運行過程

使用自定義特性的步驟:

1. 定義特性類,類必須直接或間接繼承字Attribute類

2. 在需要用的該特性的目標元素上添加特性

3. 在使用添加了特性的類的使用,獲取並使用自特定特性的信息

推薦:http://www.cnblogs.com/roucheng/p/dushubiji.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM