attribute的用法--C#

一直以來都沒理解attribute是個什麼東西,也沒怎麼用,但是看msdn或者git上源碼使用的還是蠻頻繁的,今天好好整理了下,寫下自己的理解和例子:

attribute主要用來說明代碼段的的信息,標誌等;可以一種元數據結構,不會影響到代碼段的結果。這個代碼段可以是class,struct,method,constructor等結構,下面會給出反編譯源碼說明哪些代碼段可以作爲目標。

    1,.NET內建attribute
         [AttributeUsage]

  AttributeUsage主要用來限定attribute可以在哪些情況下下使用,下面是AtttributeUsage的多個構造函數中的一個,其他不贅述:

internal AttributeUsageAttribute(AttributeTargets validOn, bool allowMultiple, bool inherited)
    {
      this.m_attributeTarget = validOn;
      this.m_allowMultiple = allowMultiple;
      this.m_inherited = inherited;
    }
   參數說明:

       1),AttributeTarges必要的參數,反編譯得到attribute的目標:    

public enum AttributeTargets
  {
    [__DynamicallyInvokable] Assembly = 1,
    [__DynamicallyInvokable] Module = 2,
    [__DynamicallyInvokable] Class = 4,
    [__DynamicallyInvokable] Struct = 8,
    [__DynamicallyInvokable] Enum = 16, // 0x00000010
    [__DynamicallyInvokable] Constructor = 32, // 0x00000020
    [__DynamicallyInvokable] Method = 64, // 0x00000040
    [__DynamicallyInvokable] Property = 128, // 0x00000080
    [__DynamicallyInvokable] Field = 256, // 0x00000100
    [__DynamicallyInvokable] Event = 512, // 0x00000200
    [__DynamicallyInvokable] Interface = 1024, // 0x00000400
    [__DynamicallyInvokable] Parameter = 2048, // 0x00000800
    [__DynamicallyInvokable] Delegate = 4096, // 0x00001000
    [__DynamicallyInvokable] ReturnValue = 8192, // 0x00002000
    [__DynamicallyInvokable] GenericParameter = 16384, // 0x00004000
    [__DynamicallyInvokable] All = GenericParameter | ReturnValue | Delegate | Parameter | Interface | Event | Field | Property | Method | Constructor | Enum | Struct | Class | Module | Assembly, // 0x00007FFF
  }
         2),allowMutiple是bool類型,可選的參數;ture表示可以在同一個代碼段多次使用,默認的是false;

         3),inherited是bool類型,可選的參數;ture表示在派生類中繼承,默認的值false;

         [Obsolete]

        主要用來指示代碼段是廢棄的,並通知編譯器,編譯器將會給出警告或者錯誤;

        用法:[Obsolete(message)]  和[Obsolte(message(string),iserror(bool))]

        message:描述代碼段廢棄的原因,並指出替代者;iserror:當它是true時,編譯器報錯,默認時false

    這裏放代碼的話看不出來編譯錯誤,上圖明顯顯示錯誤,並指示應該時NewMethod。

         [Conditional]

         主要用來定義一個預定義符號,作爲編譯條件,類似#ifdef的作用,下面例子說明用法:

#define Test
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
namespace Experiments
{
    class Program
    {
        static void Main(string[] args)
        {
            
            System.Console.ReadKey();
            DoWork();
        }
 
        [Conditional("Test")]
        static void DoWork()
        {
            for (int i = 0; i < 100; i++)
            {
                Console.WriteLine(i);
                Thread.Sleep(100);
            }
        }
    }
}
  當沒有定義#define Test,DoWork方法不執行

         [CallerMemberName]

  可以自動展示調用者的名字,用在INotifyPerprotyChanged例子:

public class MyUIClass : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
 
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                if (value != _name)
                {
                    _name = value;
                    RaisePropertyChanged();   // notice that "Name" is not needed here explicitly
                }
            }
        }
    }
2,自定義attribute
     自定義的attribute必須要繼承自Attribute基類,其參數按照MSDN解釋分爲位置參數(positional parameter)和可選的命名參數(named parameter)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Experiments
{
    [AttributeUsage(AttributeTargets.Class
                    |AttributeTargets.Constructor
                    |AttributeTargets.Field
                    |AttributeTargets.Method
                    |AttributeTargets.Property, AllowMultiple = true)]
    public class DevelopLog:Attribute
    {
        //positional parameter
        private string _developer;
        private string _reviewer;
        private string _lastModTime;
        //named parameter
        private string msg;         
 
        public string Developer { get => _developer;  }
        public string Reviewer { get => _reviewer; }
        public string LastModTime { get => _lastModTime;  }
        public string Msg { get => msg; set => msg = value; }
 
        public DevelopLog(string dev, string rv, string lmt)
        {
            _developer = dev;
            _reviewer = rv;
            _lastModTime = lmt;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Experiments
{
    
    [DevelopLog("zhangsan", "boss", "20180807", Msg = "create class")]
    [DevelopLog("lisi", "boss", "20180807", Msg = "add method dowork")]
    public class Student
    {
        private string _name;
        private string _age;
 
        public Student(string n, string a)
        {
            _name = n;
            _age = a;
        }
 
        [DevelopLog("zhangsan", "boss", "20180807")]
        public void EvertyDayDoThing()
        {
 
        }
        [DevelopLog("zhangsan", "boss", "20180807")]
        public void MoringDo()
        {
 
        }
        [DevelopLog("lisi", "boss", "20180808")]
        public void NoonDo()
        {
 
        }
 
        [DevelopLog("zhangsan", "boss", "20180807", Msg="paly game all day and not do homework")]
        public void PlayGame()
        {
 
        }
    }
}
  然後在實際應用中,我們可以通過reflection來獲取上面描述的attribute,從而獲取有價值的信息
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章