[C#] Attribute

什么是Attribute?我们为什么需要Attribute?

Attribute是一段附加信息,该信息可以附加在方法,类,名称空间,程序集上。例如下面的例子中,将Method1设为“Obsolete”属性。

    public class MyClass
    {
        [Obsolete]
        public void Method1()
        {
        }

        public void NewMethod()
        {
        }
    }

我们在代码中调用Method1,这个方法,

简单的说,Attribute其实没有做任何代码相关的工作,只是给开发者一段直观的提示信息。在“Obsolete” 属性上,如果你需要给开发者更多信息。例如:

        [Obsolete("Please use NewMethod")]
        public void Method1()
        {
        }

如果需要限制开发者使用Method1,可以在Obsolete属性中,传递“true”,代码如下:

        [Obsolete("Please use NewMethod", true)]
        public void Method1()
        {
        }

此时再调用Method1,则编译时直接报错,而不是一个Warning信息。

怎么创建自定义Attribute

上述代码中使用的Obsolete属性是系统提供的。自定义Attribute只需要继承Attribute类即可。例如:

    public class HelpAttribute : Attribute
    {
        public string HelpText { get; set; }
    }

    [Help(HelpText ="This is a class")]
    public class Customer
    {
        private string _customerCode;

        [Help(HelpText = "This is a property")]
        public string CustomerCode
        {
            get { return _customerCode; }
            set { _customerCode = value; }
        }

        [Help(HelpText ="This is a method")]
        public void Add()
        {

        }
    }

自定义了一个HelpAttribute,然后将它应用在类/方法/属性上面。

是否可以限制一个自定义Attribute只应用在方法或者属性上面?

对HelpAttribute类进行如下修改即可,

    [AttributeUsage(AttributeTargets.Method)]
    public class HelpAttribute : Attribute
    {
        public string HelpText { get; set; }
    }

在HelpAttribute上面添加AttributeUsage属性,将AttributeTargets设置为Method即可。AttributeTargets是一个枚举类型,更多信息:

https://msdn.microsoft.com/en-us/library/system.attributetargets(v=vs.110).aspx

除了可以描述一段信息之外,Attribute还可以做什么?

例如下面的例子,限制一个字段长度的Attribute。定义一个CheckAttribute,并在Customer的CustomerCode的长度,

    [AttributeUsage(AttributeTargets.Property)]
    public class CheckAttribute : Attribute
    {
        public int MaxLength { get; set; }
    }

    public class Customer
    {
        private string _customerCode;

        [Check(MaxLength = 10)]
        public string CustomerCode
        {
            get { return _customerCode; }
            set { _customerCode = value; }
        }

        [Help(HelpText ="This is a method")]
        public void Add()
        {

        }
    }

下面使用反射(Reflection)来读取Attribute的值,并做校验,

    Customer obj = new Customer();
    obj.CustomerCode = "12345678901";

    // Reflect
    // Get the type of the object
    Type type = obj.GetType();

    // Loop through all properties
    foreach (PropertyInfo p in type.GetProperties())
    {
        foreach (Attribute atr in p.GetCustomAttributes(false))
        {
            CheckAttribute c = atr as CheckAttribute;

            if(c != null)
            {
                if(p.Name == "CustomerCode")
                {
                    // Do the length check and raise exception accordingly
                    if(obj.CustomerCode.Length > c.MaxLength)
                    {
                        throw new Exception("Max length issues.");
                    }
                }
            }
        }
    }

自定义Attribute是否可以被继承?

可以。例如,自定义一个CheckExAttribute继承自CheckAttribute

如果不想被其它Attribute继承,使用Inherited =false标记即可,

    [AttributeUsage(AttributeTargets.Property,Inherited =false)]
    public class CheckAttribute : Attribute
    {
        public int MaxLength { get; set; }
    }

如果一个属性只想被调用一次,可以使用AllowMultiple=false

    [AttributeUsage(AttributeTargets.Property,AllowMultiple=false)]
    class Check : Attribute
    {
        public int MaxLength { get; set; }
    }

感谢您的阅读!

posted @ 2017-08-22 12:42  Yang-Fei  阅读(400)  评论(0编辑  收藏  举报