一、特性在哪里应用?
特性是无处不在的,在EF-MVC-WebService-UnitTest等等,那么她长什么样子呢? [特性名称]
二、特性是个什么?
可以发现,特性就是一个类,直接或间接继承自Attribute父类。三、自定义特性
系统自带的特性就不用说了,那么我们可不可以自己定义一个特性呢?当然可以!
自定义特性分为以下4步:
- 声明自定义特性;
- 构建自定义特性;
- 在目标程序上应用自定义特性
- 通过反射访问特性
开始操作
1、自定义一个检查长度是否符合规范的特性类
AttributeUsage
- 预定义特性 AttributeUsage 描述了如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。
[AttributeUsage(
validon,
AllowMultiple=allowmultiple,
Inherited=inherited
)]
其中:
- 参数 validon 规定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
- 参数 allowmultiple(可选的)为该特性的 AllowMultiple 属性(property)提供一个布尔值。如果为 true,则该特性是多用的。默认值是 false(单用的)。
- 参数 inherited(可选的)为该特性的 Inherited 属性(property)提供一个布尔值。如果为 true,则该特性可被派生类继承。默认值是 false(不被继承)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AttributeDemo
{
[AttributeUsage(AttributeTargets.Property)]//约束特性只能给属性声明
public class StringLengthAttribute: Attribute //继承父类,约定俗成以Attribute结尾
{
private int Min;
private int Max;
public StringLengthAttribute(int min,int max)//调用特性时给字段赋值
{
this.Min = min;
this.Max = max;
}
public bool Validate<T>(T t)
{
//传入的值不能为空,大于最小长度,小于最长长度,字符串符合返回True,否则False
return t != null && t.ToString().Length >= Min && t.ToString().Length <= Max;
}
}
}
2、建立一个用户类,并且添加特性
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AttributeDemo
{
public class UsersInfo
{
/// <summary>
/// 用户账号
/// </summary>
[StringLength(5,15)]//Attribute可以省略
public string Account { get; set; }
}
}
3、建立一个第三方类,来反射获取特性,执行里面的方法
通过反射遍历类型的属性,检测是否存在特性,存在就执行特性的方法,返回值
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace AttributeDemo
{
public static class AttributeExend//特性扩展类,第三方类
{
public static bool Validate<T>(this T t)//使用扩展方法
{
Type type = t.GetType();//获取类型
foreach (var prop in type.GetProperties())//遍历类型的属性
{
if (prop.IsDefined(typeof(StringLengthAttribute), true))//检查特性是否存在
{
//存在的话获取特性
StringLengthAttribute attribute = (StringLengthAttribute)prop.GetCustomAttribute(typeof(StringLengthAttribute), true);
//执行特性的方法,传递当前属性的值过去
return attribute.Validate(prop.GetValue(t));//检查是否符合特性,返回方法的值
}
}
return true;//没有特性就返回true
}
}
}
4、客户端调用
UsersInfo users = new UsersInfo();
users.Account = "1123213";
if (users.Validate())//这返回的是一个bool值,true代表验证通过,false没有
{
Console.WriteLine("验证成功");
}
else
{
Console.WriteLine("请输入5-15的字符串");
}
四、自我理解
- 我们会发现特性本身是没有用的。
- 我们只能通过反射获取特性,先isdefind检测,在获取
- 程序运行的时候就可以找到特性,就可以发挥特性的作业,提供额外的信息,或额外的动作。
- 所以,我们需要一个第三方,在这里去主动检测特性,并提供功能。
- 特性本身是没有用的
五、结束语
你不能拥有的,别人替你去拥有