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,从而获取有价值的信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值