C# 特性🔥(Attribute)
什么是特性🙏
特性(Attribute)是用于在運行時傳遞程式中各種元素(比如類、方法、結構、列舉、組件等)的行為資訊的宣告性標簽,您可以通過使用特性向程式添加宣告性資訊,一個宣告性標簽是通過放置在它所應用的元素前面的方括號([ ])來描述的,
特性(Attribute)用于添加元資料,如編譯器指令和注釋、描述、方法、類等其他資訊,.Net 框架提供了兩種型別的特性:預定義特性和自定義特性,
特性作用🎅
用以將元資料或宣告資訊與代碼(程 序集、型別、?方法、屬性等)相關聯
特性描述🎄
- 特性可向程式中添加元資料
- 可以將一個或多個特性應用到整個程式集,模塊或較小的程式元素(如類和屬性)—一個程式元素可以添加多個特性
- 特性可以與?方法和屬性相同的?方式接受引數—特性可以接受引數
- 程式可以使用反射檢查自己的元資料或其他程式內的元資料
- 特性(元資料)是在編譯之后就定義好的
元資料🎁(Meta Data)
描述:元資料是一種?進制資訊,?用以對存盤在公共語?言運?行行庫可移植 可執?檔案 (PE) 檔案或存盤在記憶體中的程式進行描述,將您的代
碼編譯為 PE 檔案時,便便會將元資料插入到該檔案的一部分中,而 將代碼轉換為 Microsoft 中間語言 (MSIL)
并將其插?入到該檔案的 另一部分中,在模塊或程式集中定義和參考的每個型別和成員都
將在元資料中進行說明,當執?代碼時,運?庫將元資料加載到記憶體中,并參考它來發現有關代碼的類、成員、繼承等資訊,

預定義特性💬
AttributeUsage🎉
這個重要還難!
描述:預定義特性 AttributeUsage 主要?用于標示?自定義特性可以 應?用到哪些型別的程式元素上,這個資訊由第?一個引數給出
實體:
[AttributeUsage(
validon,//規定特性可被放置的語言元素,它是列舉? AttributeTargets 的值的組合,默認值是 AttributeTargets.All
AllowMultiple=allowmultiple, //如果為 true,則該特性可以在同一個元素多次使?用,默認值是 false(不不可多次使?用)
Inherited=inherited//如果為 true,則該特性可被派生類繼承,默認值是 false(不被繼承) )]
1.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[AttributeUsage(AttributeTargets.Class,AllowMultiple =true,Inherited =true)]
public class AuthorAttribute : Attribute
{
public string author;
public string lastDate;//最后修改的日期
public string LastDate
{
get
{
return lastDate;
}
set
{
lastDate = value;
}
}
//當前特性的建構式
public AuthorAttribute(string author)
{
this.author = author;
}
}
[AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
public class MyConditionAttribute : Attribute
{
public MyConditionAttribute()
{
}
}
[Author("Albert",lastDate = "1010.6.13"),Author("Tom",lastDate ="1010.10.13")]
public class UserAttributeDemo : MonoBehaviour
{
public static string log="abc";
[MyCondition]
public static void ShowLog()
{
Debug.Log(log);
}
}
2.using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection;
[AddComponentMenu("My/UsesAttributeObserver")]
[RequireComponent(typeof(Rigidbody),typeof(BoxCollider))]//組件依賴
public class UsesAttributeObserver : MonoBehaviour
{
[Header("日志延遲時間")]
[Range(0,1000)]
public float logelayTime=100;
[SerializeField]//讓私有欄位也可以顯示到監視器面板上
private string name;
[ColorUsage(false)]
public Color col;
private void Start()
{
InvokeMethodByAttribute(typeof(MyConditionAttribute),"ShowLog",true,true);
}
/// <summary>
/// 執行某個方法依據某個特性
/// </summary>
/// <param name="methodClasstype">方法所在的類的型別</param>
/// <param name="methodName">方法名</param>
/// <param name="isStatic">是否靜態</param>
/// <param name="isPublic">是否公有</param>
/// <param name="methodObj">成員方法所在物件</param>
///
private void InvokeMethodByAttribute(Type methodClasstype, string methodName,bool isStatic,bool isPublic,object methodObj=null)
{
BindingFlags staticFlags = isStatic ? BindingFlags.Static : BindingFlags.Instance;
BindingFlags publicFlags = isPublic ? BindingFlags.Public : BindingFlags.NonPublic;
//獲取到該方法
MethodInfo info= methodClasstype.GetMethod(methodName, staticFlags | publicFlags);
//獲取MyConditionAttribute型別的特性
object[] atts= info.GetCustomAttributes(typeof(MyConditionAttribute), false);
if (atts.Length>0)
{
//info.Invoke();
}
Debug.Log("");
}
void PrintAttributeMsg()
{
//獲取型別
Type type = typeof(UserAttributeDemo);
//得到該型別的不可繼承的特性物件
object[] atts= type.GetCustomAttributes(false);
for (int i = 0; i < atts.Length; i++)
{
//判斷
if(atts[i]is AuthorAttribute)
{
//將特性轉換為該型別
AuthorAttribute authorObj = atts[i] as AuthorAttribute;
Debug.Log(authorObj.author);
Debug.Log(authorObj.lastDate);
}
}
}
}

Conditional🎉
**就是類似于一個密鑰,在方法前添加了[Conditional(“ZAY”)]特性后,使用時需要在最前邊宣告一個 #define ZAY 才能正常使用添加此特性的方法 **
描述:這個預定義特性標記了了?一個條件方法,其執行依賴于它頂的預處理識別符號, 它會引起方法調?用的條件編譯,取決于指定的值,比如 Debug 或 Trace,
[Conditional("ABC")]
1.using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
public class ConditionalDemo
{
[Conditional("ZAY")]
public static void ShowMe()
{
Debug.Log("Show Me!");
}
}
public class HasConditionDemo : MonoBehaviour
{
void Start()
{
}
}
2.
#define ZAY
using UnityEngine;
public class UseConditionalDemo : MonoBehaviour
{
void Start()
{
ConditionalDemo.ShowMe();
}
}

Obsolote🎉
可以標記此方法已過時,也可以將方法設定為直接不可用
描述: 這個預定義特性標記了不應被使?用的程式物體,它可以讓您通知編譯器?丟棄某個特定的?目 標元素,例如,當一個新方法被用在一個類中,但是您仍然想要保持類中的舊方法,您可以通過顯示一個應該使?用新方法,而不是舊方法的訊息,來把它標記為 obsolete(過時的),
示例:
[Obsolete]
[Obsolete("當前方法已過時,請使用新的方法")]
[Obsolete("過時了",false)]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class DemoFrame
{
//[Obsolete]
//[Obsolete("當前方法過時了,請使用NewDemoShowMe()替換他")]
[Obsolete("當前方法過時了,請使用NewDemoShowMe()替換他",false)]
public static void OldDemoShowMe()
{
Debug.Log("OldDemoShoeMe");
}
public static void NewDemoShowMe()
{
Debug.Log("NewDemoShowMe");
}
}
public class UseObsoleteDemo : MonoBehaviour
{
void Start()
{
DemoFrame.NewDemoShowMe();
}
}


自定義特性🎈
.Net 框架允許創建自定義特性,用于存盤宣告性的資訊,且可在運行時被檢索,該資訊根據設計標準和應用程式需要,可與任何目標元素相關,
創建并使用自定義特性包含四個步驟:
- 宣告自定義特性
- 構建自定義特性
- 在目標程式元素上應用自定義特性
- 通過反射訪問特性
最后一個步驟包含撰寫一個簡單的程式來讀取元資料以便查找各種符號,元資料是用于描述其他資料的資料和資訊,該程式應使用反射來在運行時訪問特性
示例:
我這里是在Unity里做的測驗,特性的用處也更多
//添加到選單里
[AddComponentMenu("My/UsesAttributeObserver")]
//組件依賴
[RequireComponent(typeof(Rigidbody),typeof(BoxCollider))]
[SerializeField]//讓私有欄位也可以顯示到監視器面板上
private string name;
下面是自定義特性的介紹圖

特性(Attribute) 也常跟 反射(Reflection) 進行配合作業,下次再簡單介紹一下反射的定義和用法

下面是MSDN中對特性用途的描述:
-
在 Web 服務中,使用 WebMethod 特性來標記方法,以指示該方法應該可通過 SOAP 協議進行呼叫, 有關更多資訊,請參見WebMethodAttribute,
-
描述當與本機代碼進行互動操作時如何封送方法引數,有關更多資訊,請參見 MarshalAsAttribute,
-
描述類、方法和介面的 COM 屬性,
-
使用 DllImportAttribute 類呼叫非托管代碼,
-
在標題、版本、說明或商標方面描述您的程式集,
-
描述要持久性序列化類的哪些成員,
-
描述如何映射類成員和 XML 節點以便進行 XML 序列化,
-
描述方法的安全要求,
-
指定用于強制安全性的特性,
-
由實時 (JIT) 編譯器控制優化,以便易于除錯代碼,
-
獲取有關呼叫方的資訊的方法,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/279551.html
標籤:其他
下一篇:web安全sql注入初識
