zoukankan      html  css  js  c++  java
  • 特性

    特性

    特性是一种将自定义信息添加到代码元素(程序集、类型、成员、返回值、参数和泛型类型参数)的扩展机制

    特性在没有破坏类型封装的前提下,可以加点额外的信息和行为

    定义特性

    特性是一个继承Attribute类的类,在其中可以定义属性、字段、方法、构造函数等,与正常的类并无两样,但是通常我们会以Attribute作为类名的结尾

    获取特性实例

    特性可以作为普通类来使用,但是这样就没有了意义,完全可以使用普通类

    特性的正确用法是通过[ ]对类中信息进行标注,以便对其进行扩展

    在实例化时通过反射查找类时同时查找特性,对其进行验证操作

    使用特性

    // 抽象特性,为了后面可以查找多种验证
    public abstract class AbstractValidateAttribute:Attribute
    {
        public abstract bool Validate(object value);
    }
    
    
    // 定义特性
    [AttributeUsage(AttributeTargets.Property|AttributeTargets.Field)]
    public class NotNullAttribute:AbstractValidateAttribute
    {
        public override bool Validate(object value)
        {
            return value != null ? true : false;
        }
    }
    
    // 使用特性
    public static bool Validate<T>(this T tModel) where T : BaseModel
    {
        Type type = tModel.GetType();
        foreach (var propertyInfo in type.GetProperties())
        {
            if (propertyInfo.IsDefined(typeof(AbstractValidateAttribute),true))
            {
                object[] attributeArray = propertyInfo.GetCustomAttributes(typeof(AbstractValidateAttribute), true);
                foreach (AbstractValidateAttribute attribute in attributeArray)
                {
                    if (!attribute.Validate(propertyInfo.GetValue(tModel)))
                    {
                        return false;
                    }
                }
            }
        }
    
        return true;
    }
    

    前面说特性不结合反射则基本是没有用的,这里的例子就是结合反射的一个具体例子

    首先定义了一个抽象基类,这是为了后面查找时可以查找到多个继承自该抽象类的验证特性

    接着定义了一个具体的NotNull特性,这个特性定义了一个验证方法Validate,如果值为null则返回false,不为null则返回true

    然后定义了一个名为Validate的扩展方法,注意这个方法和上面的方法不是同一个方法,该方法接收一个泛型对象,然后通过反射获取该对象的所有属性

    并判断每一个属性是否包含AbstractValidateAttribute特性的定义,也就是属性上方是否使用了[<特性>],如果有,则获取特性实例数组

    接着再通过特性的实例对象来调用前面特性定义的方法,并根据其执行结果参与判断,做出最终的判断

    在其他地方,原本直接进行处理的代码,可以添加验证代码,根据特性的结果来决定如何处理

    结果论

    在我使用特性时,最大的迷惑是如何获取到特性,以及如何将其关联起来

    [NotNull]
    public string Name { get; set; }
    

    当我们在一个类模型中定义了这样一个特性,开始的时候始终不明白

    • 怎样知道是哪个属性绑定了特性?
      • 通过反射获取到所有的属性,然后通过IsDefined方法判断是否存在指定的特性
    • 怎样使用特性?
      • 如果IsDefined判断确实定义了指定的特性,则通过 属性.GetCustomAttributes方法获取特性实例,然后调用实例方法,如果需要属性的值,可以通过反射的GetValue来获取
    • 特性什么时候生效?
      • 很遗憾附加特性并没有什么用,特性只是添加附加信息,当然也可以附加动作,但是它并不能自动执行,只能在需要的时候手动去选择执行,比如上面的定义了NotNull特性,然后为了方便还定义了Validate扩展方法,这个特性主要是用在model上的,所以如果属性定义了NotNull特性,在给model赋值时一样可以赋值null,但是我们可以在后面用到model时,选择调用Validate扩展方法,这样就可以验证这么model的值是否符合要求,符合要求继续操作,否则可以考虑抛出异常
      • 特性的重点是两个类之间提供了一种关联性,即普通类通过在某个位置使用[<特性>]来描述关联,通过反射获取到这种关联来在合适的时候执行特性类的内容,并可能会得到一个结果,这个结果作为下一步操作的依据

    本文只是暂作笔记,尚未经过斟酌,参考需谨慎

  • 相关阅读:
    jpype
    Java获取类中的所有方法
    SQL中INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN区别
    如何用命令将本地项目上传到git
    Java连接Mysql:通过配置文件
    lsof -i:port_number
    yum install lsof
    Git的基本使用方法(受益匪浅)
    [后端]gitlab之gitlab-ci自动部署
    centos7安装redis-4.0.1集群
  • 原文地址:https://www.cnblogs.com/wujuncheng/p/13717396.html
Copyright © 2011-2022 走看看