c#中的特性,以及一些思考


unity中會有像[range(0,1)]這樣的特性寫法,其非常方便的限制了變量范圍但是。我一直很好奇這是怎么實現的,所以翻了翻其他博主對其的解釋和應用。

 

一,什么是特性

  有一種解釋我很能接受,特性就像牡蠣附在對象上。其本質也是一種對象,特殊之處在於其編譯時就存在了,也就是在程序運行之前就存在了。

二,如何定義一個特性

 1 namespace UnityEngine
 2 {
 3 
 4     [AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
 5 
 6     public abstract class PropertyAttribute : Attribute
 7     {
 8         protected PropertyAttribute();
 9 
10         public int order { get; set; }
11     }
12 }

只是啥=。= 不就是一個對象嗎,我copy了unity中的一段特性代碼。事實上所有的特性都繼承 Attribute,unity在中多封裝了一層 PropertyAttribute ,且給每個特性加上了一個ID。

所以定義一個特性只需要繼承 Attribute 就可以了。

那么其上面的特性 AttributeUsage又表示什么呢,

三,特性的使用

AttributeUsage=。=直接說明了特性的使用范圍嘛,后面標注了幾個屬性
AttributeTargets.Field代表可以附着在字段上,其他地方不能加不上這個標簽特性。AttributeTargets本身是枚舉值,且其是c#預制的特性變量。
Inherited 是否可以繼承這就很好理解了
AllowMultiple 是否能夠混合使用,也就是一個類上掛倆三個特性。

理解可這些參數之后就可以自己寫一個特性玩玩了,這里我寫一個自定義的debuginfo在unity中調用
(1)聲明
using System;
using UnityEngine;
//特性所能使用的范圍
[AttributeUsage(AttributeTargets.Method|AttributeTargets.Field
    , AllowMultiple =true)]
public class DebugerCoderAttribute : UnityEngine.PropertyAttribute
{
    private string codename;
    private string codeLasttime;
    private bool Ischeck;
    private string message;
    public DebugerCoderAttribute(string CoderName, string CodeLastTime, bool Checked)
    {
        codename = CoderName;
        codeLasttime = CodeLastTime;
        Ischeck = Checked;
        message = "";      
    }

    public DebugerCoderAttribute(string CoderName, string CodeLastTime,string OtherInfo, bool Checked)
    {
        codename = CoderName;
        codeLasttime = CodeLastTime;
        Ischeck = Checked;
        message = OtherInfo;
    }
    public string ScriptsCoder
    {
        get
        {
            return codename;
        }
    }
    public string ScriptsTime
    {
        get
        {
            return codeLasttime;
        }
    }
    public bool ScriptsIsChecked
    {
        set
        {
            Ischeck = value;
        }
        get
        {
            return Ischeck;
        }
    }
    public string Message
    {
        set
        {
               message = value;
        }
        get
        {
            return message;
        }
    }
}

  (2)腳本調用

public class TempReadJobScrpts : MonoBehaviour {

    [DebugerCoder("yang", "1995", false, Message = "只能注釋方法名,在MyinfoDebug中可以修改完成指定位置信息讀取")]
    public void MyMethod()
    {

    }
}

(3)反射調用(更好點可以寫到editor中運行達到自行檢測運行腳本方法順序的目的)

/*此類可以寫在editor中運行達到自運行檢測的目的*/
public class MyInfoDebuger : MonoBehaviour {
    public GameObject SelectObj;
    /*目前只能讀取腳本為 SelectObj中 TempReadJobScrpts的注釋信息*/
    public readonly string TempReadJobScrpts= "TempReadJobScrpts";
    public bool IsReadBug = true;
    public bool ShowAllMehodOfScripts = false;
    // Use this for initialization
    void Start () {
        if (IsReadBug)
         ShowDebugInfo();
    }
    void GetAllMyPrivareScripts()
    {
        //獲取所有自定義腳本的名字
    }
    public void ShowDebugInfo()
    {//這里需要修改成獲取所有腳本的信息參數
        try
        {
            //僅在unity 中需要使用  此處非自執行。。便利腳本效率比較低
            //當方法加入public時 此處可以獲取
            MonoBehaviour[] monos = SelectObj.GetComponents<MonoBehaviour>();
            foreach (var item in monos)
            {
                if (item.GetType().ToString().EndsWith(TempReadJobScrpts))
                {
                    Debug.Log("is reading>>:" + ((MonoBehaviour)item).GetType());
                    //顯示有標簽的方法 此處只能用在方法上    此處設置的是私有和共有方法
                    MethodInfo[] meths = ((MonoBehaviour)item).GetType().GetMethods(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public);
                    foreach (MethodInfo met in meths)
                    {                        
                        if (Attribute.GetCustomAttributes(met).Length>0)
                        {
                            if (ShowAllMehodOfScripts)
                                Debug.Log(met.Name);

                            Attribute[] attris = Attribute.GetCustomAttributes(met);                         
                            foreach (Attribute at in attris)
                            {
                                if (at.GetType() == typeof(DebugerCoderAttribute))
                                {
                                    DebugerCoderAttribute info = (DebugerCoderAttribute)at;
                                    Debug.Log("coder:" + info.ScriptsCoder + ","
                                        + " message:" + info.Message+" date:"+info.ScriptsTime);
                                }
                            }
                        }
                    }

                }
            }
        }
        catch (System.Exception ex)
        {
            Debug.Log(this.name+" "+ ex.ToString());
        }

    }
}

 運行結構:

 


免責聲明!

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



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