特性

特性

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

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

定义特性

特性是一个继承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的值是否符合要求,符合要求继续操作,否则可以考虑抛出异常
    • 特性的重点是两个类之间提供了一种关联性,即普通类通过在某个位置使用[<特性>]来描述关联,通过反射获取到这种关联来在合适的时候执行特性类的内容,并可能会得到一个结果,这个结果作为下一步操作的依据

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

原文地址:https://www.cnblogs.com/wujuncheng/p/13717396.html