特性应用
取得枚举类型的注释
平时开发时,经常会用到枚举类型及其相关判断,而有时我们想显示枚举类型的注释,怎么办?下面用特性来解决这个问题。
namespace AttributeDemo.CustomAttributes { public class RemarkAttribute : Attribute { private readonly string remark; public RemarkAttribute(string remark) { this.remark = remark; } public string GetRemark() { return remark; } } } namespace AttributeDemo.Extensions { public enum UserState { /// <summary> /// 正常 /// </summary> [RemarkAttribute("正常")] Normal = 0, /// <summary> /// 冻结 /// </summary> [RemarkAttribute("冻结")] Frozen, /// <summary> /// 删除 /// </summary> [RemarkAttribute("删除")] Deleted } public static class RemarkExtension { public static string GetRemark(this Enum value) { Type type = value.GetType(); FieldInfo field = type.GetField(value.ToString()); if (field.IsDefined(typeof(RemarkAttribute), true)) { RemarkAttribute attr = field.GetCustomAttribute<RemarkAttribute>(); return attr.GetRemark(); } return value.ToString(); } } }
使用
UserState userState = UserState.Normal; Console.WriteLine(userState.GetRemark());
数据有效性检查
一般对于用户提交的数据,我们都需要进行数据有效性的检查,之后才能提交到数据库。本次我们使用特性,优雅的解决这个问题。
声明检查数据长度的特性(因为想把数据校验作为一个共通处理,因此需要首先声明一个抽象类):
namespace AttributeDemo.CustomAttributes { public abstract class CustomValidateAttribute : Attribute { public abstract bool Validate(object value); } public class LengthValidateAttribute : CustomValidateAttribute { private readonly int minLen; private readonly int maxLen; public LengthValidateAttribute(int minLen, int maxLen) { this.minLen = minLen; this.maxLen = maxLen; } public override bool Validate(object value) { if (value != null && !string.IsNullOrEmpty(value.ToString())) { int len = value.ToString().Length; if (len >= minLen && len <= maxLen) { return true; } } return false; } } }
把特性附加到类中
namespace AttributeDemo { //可以对类整体使用 [CustomAttribute(description:"类特性示例",remark: "类特性")] public class Student { public int Id { get; set; } public string Name { get; set; } [LengthValidateAttribute(16, 100)]//追加对邮箱的长度检查 public string EMail { get; set; } //可以对属性字段使用 [CustomAttribute(description: "属性示例", remark: "属性特性")] [LengthValidateAttribute(6, 9)]//追加对电话号码的长度检查 public string PhoneNumber { get; set; } //可以对方法使用 [CustomAttribute(description: "方法示例", remark: "方法特性")] public void Study() { Console.WriteLine($"{Name}正在学习中。。。"); } //可以对返回值使用 [return: CustomAttribute(description: "返回值示例", remark: "返回值特性")] public string SayHi([CustomAttribute(description: "参数示例", remark: "参数特性")] string name)//可以对参数列表使用 { return $"Hello {name}"; } } }
再对Student
类添加一个扩展方法(如果想对更广泛范围的对象进行数据校验,可以对它们的基类追加扩展方法):
public static class ValidateExtension { public static bool Validate(this Student value) { int errCount = 0; Type type = value.GetType(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo property in properties) { if (property.IsDefined(typeof(CustomValidateAttribute), true)) { IEnumerable<CustomValidateAttribute> attris = property.GetCustomAttributes<CustomValidateAttribute>(); foreach (CustomValidateAttribute attr in attris) { if (!attr.Validate(property.GetValue(value))) { Console.WriteLine($"数据校验失败:字段[{property.Name}]"); errCount++; } } } } return errCount == 0 ? true : false; } }
调用数据校验:
Student stu = new Student { Id = 1, EMail = "xxxxx@xxxx.com", Name = "brein", PhoneNumber = "1234567890" }; stu.Validate();
输出校验结果:
数据校验失败:字段[PhoneNumber] 数据校验失败:字段[EMail]
以上,是两个平时用的比较多的关于特性的应用场景。在ASP.NET Core
中,特性还有更多应用场景,例如:Filter
,Validate
,MVC
/API
相关特性,AOP
应用等等。可以说特性无处不在且非常重要。充分掌握特性相关知识,是掌握ASP.NET Core
的充分必要条件。