• [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; }
        }

    感谢您的阅读!

  • 相关阅读:
    spring源码-BeanFactoryPostProcessor-3.2
    web之前端获取上传图片并展示
    spring源码-增强容器xml解析-3.1
    spring源码-bean之增强初始化-3
    spring源码-bean之加载-2
    spring源码-bean之初始化-1
    spring源码-开篇
    java之扫描包里面的class文件
    vuex状态持久化
    Vue 使用 vuelidate 实现表单验证
  • 原文地址:https://www.cnblogs.com/yang-fei/p/7411040.html
Copyright © 2020-2023  润新知