zoukankan      html  css  js  c++  java
  • C#中特性(Attribute)的使用

    解读:首先特性是一个类,它继承于Attribute。它对程序中的元素进行标注,如类型、字段、方法和属性等。

    Attribute是程序代码的一部分,它不会被编译器丢弃,而且还会被编译器编译进程序集(Assembly)的元数据(Metadata)里。

    新建一个CustomAttribute的类:

    public class CustomAttribute:Attribute
    {
        public CustomAttribute()
        {
            Console.WriteLine(nameof(CustomAttribute));
        }
    }

    在建一个Department类,在类上面加上Custom特性:

    [Custom]
    public class Department
    {
        public Guid id { get; set; }
        public string name { get; set; }
    
        public void GetName()
        {
            Console.WriteLine(nameof(GetName));
        }
    }

    我们反编译Department类查看一下

    特性添加后,编译会在元素内部产生IL,在metadata中会有记录(这样就可以通过反射操作它),但是没办法直接使用。

    无论是在类或类中的元素上面添加特性,反编译时会看看特性会在类或类中的元素里面生成一个构造(.ctor())。

    特性的多重修饰

     

    AllowMultiple=true是指在一个(元素)类中可以多重修饰
    AttributeTargets.All表示任何元素类型都可以用其修饰

     

    特性其它语法:

     新建一个Student的类,给这个类加上CustomAttribute的特性

    [CustomAttribute(123, details = "call")]
    public class Students
    {
        public int id { get; set; }
        
    [CustomAttribute]
    public string name { get; set; }
        [Custom]
        [return: Custom]
        public void Method([Custom] string name)
        {
          Console.WriteLine("success");
        }
    }

    再建一个Manage类,找出Students类上的特性,并进行调用操作等...

    public static class Manage
    {
        public static void show(Students students)
        {
            //获取类型
            Type type = typeof(Students);
            //查找是否有CustomAttribute这个特性
            if (type.IsDefined(typeof(CustomAttribute), true))
            {
                //实例化得到一个CustomAttribute类型
                //通过反射创建对象
                CustomAttribute attribute = (CustomAttribute)type.GetCustomAttribute(typeof(CustomAttribute), true);
                Console.WriteLine($"{attribute.details}");
    //调用方法 attribute.show(); } } }

    调用:

    Students students = new Students();
    Manage.show(students);

    找出Students类中属性上的的特性

    //name为字段名
    PropertyInfo prop = type.GetProperty("name"); if (prop.IsDefined(typeof(CustomAttribute), true)) { //实例化得到一个CustomAttribute类型 //通过反射创建对象 CustomAttribute attribute = (CustomAttribute)prop.GetCustomAttribute(typeof(CustomAttribute), true); Console.WriteLine($"{attribute.details}"); attribute.show(); }

    找出Students类中方法上的特性

    //Method为方法名
    MethodInfo method = type.GetMethod("Method"); if (method.IsDefined(typeof(CustomAttribute), true)) { //实例化得到一个CustomAttribute类型 //通过反射创建对象 CustomAttribute attribute = (CustomAttribute)method.GetCustomAttribute(typeof(CustomAttribute), true); Console.WriteLine($"{attribute.details}"); attribute.show(); }

    找出Students类中方法中参数的特性

    ParameterInfo parameter = method.GetParameters()[0];
    if (parameter.IsDefined(typeof(CustomAttribute), true))
    {
        //实例化得到一个CustomAttribute类型
        //通过反射创建对象
        CustomAttribute attribute = (CustomAttribute)parameter.GetCustomAttribute(typeof(CustomAttribute), true);
        Console.WriteLine($"{attribute.details}");
        attribute.show();
    }

    找出Students类中方法中返回值的特性

    ParameterInfo returnParameter = method.ReturnParameter;
    if (returnParameter.IsDefined(typeof(CustomAttribute), true))
    {
        //实例化得到一个CustomAttribute类型
        //通过反射创建对象
        CustomAttribute attribute = (CustomAttribute)returnParameter.GetCustomAttribute(typeof(CustomAttribute), true);
        Console.WriteLine($"{attribute.details}");
        attribute.show();
    }

    通过上面的代码可以知道,特性可以在没有破坏封装的前提下,可以加点额外的信息和行为,充当补充类使用。

    通过特性操作枚举数据,获取枚举字段上的描述信息

    public class RemarkExtension
    {
        /// <summary>
        /// 用户状态
        /// </summary>
        public enum UserState
        {
            [Remark("正常")]
            Normal = 0,//正常  左边字段名称,右边是值
            [Remark("冻结")]
            Frozen = 1,//冻结
            [Remark("删除")]
            Deleted = 2//删除
        }
    
        public class RemarkAttribute : Attribute
        {
            public RemarkAttribute(string remarks)
            {
                this._remarks = remarks;
            }
            public string _remarks;
    
            public string GetRemark()
            {
                return this._remarks;
            }
        }
    }
    
    public static class RemarksExtension
    {
    //扩展方法是静态类中的静态方法,在参数类型前加一个this.可以通过这个类型实例直接调用这个方法。
    public static string GetRemarks(this Enum value) { //获取类型 Type type = value.GetType(); //找到这个字段 FieldInfo fieldInto = type.GetField(value.ToString()); //这个字段上面是否有RemarkAttribute属性 if (fieldInto.IsDefined(typeof(RemarkAttribute), true)) {
    //实例化,将参数赋值给_remarks RemarkAttribute attribute
    = (RemarkAttribute)fieldInto.GetCustomAttribute(typeof(RemarkAttribute)); //取值
    return attribute.GetRemark(); } else { return value.ToString(); } } }

    调用:

    UserState userState = UserState.Normal;
    Console.WriteLine(userState.GetRemarks());
    Console.WriteLine(UserState.Frozen.GetRemarks());
    Console.WriteLine(UserState.Deleted.GetRemarks());

     通过特性做数据校验

    public static class ValidataExtension
    {
        /// <summary>
        /// 一个object的扩展方法
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static bool Validata(this object o)
        {
            Type type = o.GetType();
            //循环对象里的所有属性
            foreach (var prop in type.GetProperties())
            {
                //查看属性上面是否有LongAttribute这个特性
                //if (prop.IsDefined(typeof(LongAttribute), true))
                //{
                //    LongAttribute attribute = (LongAttribute)prop.GetCustomAttribute(typeof(LongAttribute), true);
                //    if (!attribute.Validata(prop.GetValue(o)))
                //    {
                //        return false;
                //    }
                //}
    
                //查看属性上面是否有LengAttribute这个特性
                //if (prop.IsDefined(typeof(LengAttribute), true))
                //{
                //    LengAttribute attribute = (LengAttribute)prop.GetCustomAttribute(typeof(LengAttribute), true);
                //    if (!attribute.Validata(prop.GetValue(o)))
                //    {
                //        return false;
                //    }
                //}
    
                if (prop.IsDefined(typeof(AbstractValidataAttribute), true))
                {
                    //GetCustomAttributes是多个
                    //GetCustomAttribute是单个
                    object[] attributeArray = prop.GetCustomAttributes(typeof(AbstractValidataAttribute), true);
                    foreach (AbstractValidataAttribute attribute in attributeArray)
                    {
                        if (!attribute.Validata(prop.GetValue(o)))
                        {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
    }
    
    /// <summary>
    /// 声明一个抽象类,其它的特性类继承于它
    /// </summary>
    public abstract class AbstractValidataAttribute : Attribute
    {
        public abstract bool Validata(object value);
    }
    
    
    /// <summary>
    /// 判断string数据的长度
    /// </summary>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
    // public class LengAttribute : Attribute
    public class LengAttribute : AbstractValidataAttribute
    {
        private long _min = 0;
        private long _max = 0;
        public LengAttribute(long min, long max)
        {
            this._max = max;
            this._min = min;
        }
    
        /// <summary>
        /// 重写父类Validata方法
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override bool Validata(object value)
        {
            if (value != null && !string.IsNullOrWhiteSpace(value.ToString()))
            {
                int length = value.ToString().Length;
                if (length > this._min && length < this._max)
                {
                    return true;
                }
            }
            return false;
        }
    }
    
    //public class LongAttribute : Attribute
    /// <summary>
    /// 判断数据的范围
    /// </summary>
    public class LongAttribute : AbstractValidataAttribute
    {
        private long _min = 0;
        private long _max = 0;
        public LongAttribute(long min, long max)
        {
            this._max = max;
            this._min = min;
        }
    
        public override bool Validata(object value)
        {
            if (value != null && !string.IsNullOrWhiteSpace(value.ToString()))
            {
                //判断是否为long类型,如果是直接给到result
                if (long.TryParse(value.ToString(), out long result))
                {
                    if (result > this._min && result < this._max)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    }
    public class Students
    {
        public int id { get; set; }
    
        [LengAttribute(5, 10)]
        public string name { get; set; }
    
        [LengAttribute(10, 20)]
        public string Acount { get; set; }
    
        [LongAttribute(10001, 999999999999)]
        public long QQ { get; set; }
    
        public long _QQ2 = 0;
    
        public long QQ2
        {
            get
            {
                return this._QQ2;
            }
            set
            {
                if (value > 10001 && value < 99999999999)
                {
                    _QQ2 = value;
                }
                else
                {
                    throw new Exception("Data error!");
                }
            }
        }
    }

    调用:

    Students students = new Students();
    students.study();
    students.name = "JavaJava";
    students.QQ = 999999;
    students.Acount = "c#c#c#c#c#c#c#c#";
    students.Validata();
  • 相关阅读:
    Hibernate使用笔记
    svn树冲突的解决方法
    SVN 清理失败的解决方法
    类的实现
    lua元表
    lua中table的常用方法
    C/C++作用域运算符::
    Cocos2d-x Lua 学习
    Lua学习
    吾 三十而望
  • 原文地址:https://www.cnblogs.com/zhangnever/p/13199106.html
Copyright © 2011-2022 走看看