文章出處

這兩天事情比較多,沒有來得及更新,現在把我這兩天看的attributes相關內容進行整理。

涉及到的相關概念包括:

  • C#中的特性概念及用法
  • 創建自己的特性以及通過反射訪問特性

C#中的特性概念以及用法:

  這個特性的概念,我還是比較喜歡稱之為注解屬性,官網上的定義,

特性具有以下屬性:

  • 特性可向程序中添加元數據。 元數據是有關在程序中定義的類型的信息。 所有的 .NET 程序集都包含指定的一組元數據,這些元數據描述在程序集中定義的類型和類型成員。 可以添加自定義特性,以指定所需的任何附加信息。 

  • 可以將一個或多個特性應用到整個程序集、模塊或較小的程序元素(如類和屬性)。

  • 特性可以與方法和屬性相同的方式接受參數。

  • 程序可以使用反射檢查自己的元數據或其他程序內的元數據。

  其實說白了,就是程序中的"[]"中括號之中的內容。

  一個聲明中可以放置多個特性,某些特性可以多次賦給一個聲明。

  某些特性對于給定實體可以指定多次。 例如,ConditionalAttribute 就是一個可多次使用的特性:

  

1 [Conditional("DEBUG"), Conditional("TEST1")]
2 void TraceMethod()
3 {
4      // ...
5 }

  這里需要注意一點,根據約定,所有特性名稱都以單詞“Attribute”結束,以便將它們與“.NET Framework”中的其他項區分。 但是,在代碼中使用特性時,不需要指定 attribute 后綴。 例如,[DllImport] 雖等效于 [DllImportAttribute],但 DllImportAttribute 才是該特性在 .NET Framework 中的實際名稱。

特性的參數:

  許多特性都有參數,而這些參數可以是定位參數、未命名參數或命名參數。 任何定位參數都必須按特定順序指定并且不能省略,而命名參數是可選的且可以按任意順序指定。 首先指定定位參數。 例如,這三個特性是等效的:

 

[DllImport("user32.dll")]  
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]  
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]  

 

特性的目標:

 

  特性的目標是應用該特性的實體。 例如,特性可以應用于類、特定方法或整個程序集。 默認情況下,特性應用于它后面的元素。 但是,您也可以顯式標識要將特性應用于方法還是它的參數或返回值。顯示的應用特性目標,可以這樣:

 

[target : attribute-list]  

 

  target值的列表如下:

  樣例用法:

  • 將特性應用于程序集和模塊

  

using System;
using System.Reflection;
[assembly: AssemblyTitleAttribute("Production assembly 4")]
[module: CLSCompliant(true)]
  • 在 C# 中將特性應用于方法、方法參數和方法返回值
// default: applies to method
[SomeAttr]
int Method1() { return 0; }

// applies to method
[method: SomeAttr]
int Method2() { return 0; }

// applies to return value
[return: SomeAttr]
int Method3() { return 0; }

  無論規定 SomeAttr 應用于什么目標,都必須指定 return 目標,即使 SomeAttr 被定義為僅應用于返回值也是如此。 換言之,編譯器將不使用 AttributeUsage 信息解析不明確的特性目標。

 


 

創建自己的特性以及通過反射訪問特性:

直接上代碼:(創建自己的特性)

 1 using UnityEngine;
 2 using System.Collections;
 3 using System;
 4 
 5 [AttributeUsage(AttributeTargets.Class|AttributeTargets.Field,     //特性應用的目標           
 6                           AllowMultiple=true,                      //是否可以在同一目標上放置多次
 7                           Inherited=false)]                        //是否允許子類使用此特性
 8 public class myattr : Attribute {
 9 
10     private string name;
11     public int version = 0;                                        //命名參數
12     public myattr(string _name) {
13         name = _name;
14         version = 1;
15     }
16 
17     public string GetInputName() {
18         return name;
19     }
20 }

接下來使應用特性,并通過反射訪問特性.

using UnityEngine;
using System.Collections;
using System;
using System.Reflection;

[myattr("WhiteTaken1", version = 2)]
public class MyTest1 { }
[myattr("WhiteTaken2", version = 2), myattr("WhiteTaken3", version = 1)]
public class MyTest2 { }
[myattr("WhiteTaken4")]
public class MyTest3 { }
public class MyTest4 { }
public class TestMyattr: MonoBehaviour {
    
    void Start () {
        PrintMyattrInfo(typeof(MyTest1));
        PrintMyattrInfo(typeof(MyTest2));
        PrintMyattrInfo(typeof(MyTest3));
        PrintMyattrInfo(typeof(MyTest4));
    }

    void PrintMyattrInfo(Type _type) {
        
        Debug.Log("--打印信息--" + _type);
        //應用反射
        Attribute[] att = Attribute.GetCustomAttributes(_type);
        //遍歷特性
        foreach (Attribute everyAttr in att) {
            if (everyAttr is myattr) {
                myattr _myattr = (myattr)everyAttr;
                Debug.Log("version=" + _myattr.version + ",Name=" + _myattr.GetInputName());
            }
        }
        Debug.Log("----------------------分隔符------------------------");
    }
}

運行結果:

 

創建自己的特性,需要繼承System.Attribute類,并在自己的特性類之前應用AttributeUsage特性,并設置應用目標AttributeTargets,枚舉類型成員如下。

 

 AllowMultiple是允許在一個目標上應用多次,如果為false,則只存在當前特性的一個,如果為true,當前特性可以添加多次,并用","隔開。

Inherited為false,子類不繼承父類的特性。

基本的用法,接下來就是應用到自己的程序當中,另外附上一個github中看到的自定義特性的地址

未完,待續。。。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()