///
/// 特性:中括号声明 /// /// 错觉:每一个特性都可以带来对应的功能 /// /// 实际上特性添加后,编译会在元素内部产生IL,但是我们是没办法直接使用的, /// 而且在metadata里面会有记录 /// /// 特性,本身是没用的 /// 程序运行的过程中,我们能找到特性,而且也能应用一下 /// 任何一个可以生效的特性,都是因为有地方主动使用了的一个应用场景: 可以用特性标注枚举值,以便 程序用到该枚举的 中文
public enum UserState
{ /// <summary> /// 正常 /// </summary> [Remark("正常")] Normal = 0,//左边是字段名称 右边是数据库值 哪里放描述? 注释 /// <summary> /// 冻结 /// </summary> [Remark("冻结")] Frozen = 1, /// <summary> /// 删除 /// </summary> //[Remark("删除")] Deleted = 2 } //枚举项加一个描述 实体类的属性也可以Display //别名 映射 public class RemarkAttribute : Attribute { public RemarkAttribute(string remark) { this._Remark = remark; } private string _Remark = null; public string GetRemark() { return this._Remark; } }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 attribute = (RemarkAttribute)field.GetCustomAttribute(typeof(RemarkAttribute)); return attribute.GetRemark(); } else { return value.ToString(); } }}
static void Main(string[] args){
Console.WriteLine(UserState.Frozen.GetRemark());
Console.WriteLine(UserState.Deleted.GetRemark());}
应用场景: 展示在页面的表格,每列的字段名 怎么展示? 写死吗? MVC中的 Display即为了解决该问题
做数据检查 , 比如 注册时用户名长度检查,qq检查
MVC中 常用的 model.isvalidate() 简单实现如下
核心: 自定义的attr都继承抽象类, 只需在main中调用 扩展方法, 所有实现了 该抽象特性类的的特性 都会调用 重写的validate方法 进行自己的逻辑验证
public class Student
{ [CustomAttribute] public int Id { get; set; } [Leng(5, 10)]//还有各种检查 public string Name { get; set; } [Leng(20, 50)] public string Accont { get; set; }[Long(10000, 999999999)]
public long QQ { get; set; }[CustomAttribute]
public void Study() { Console.WriteLine($"这里是{this.Name}跟着Eleven老师学习"); }[Custom()]
[return: Custom()] public string Answer([Custom]string name) { return $"This is {name}"; } }
public abstract class AbstractValidateAttribute : Attribute
{ public abstract bool Validate(object value); } public static class ValidateExtension { public static bool Validate(this object obj) { Type type = obj.GetType(); foreach (var prop in type.GetProperties()) {if (prop.IsDefined(typeof(AbstractValidateAttribute), true))
{ object[] attributeArray = prop.GetCustomAttributes(typeof(AbstractValidateAttribute), true); foreach (AbstractValidateAttribute attribute in attributeArray) { if (!attribute.Validate(prop.GetValue(obj))) { return false;//表示终止 } } } //if (prop.IsDefined(typeof(LongAttribute), true)) //{ // var attribute = (LongAttribute)prop.GetCustomAttribute(typeof(LongAttribute), true); // if (!attribute.Validate(prop.GetValue(obj))) // return false; //}//if (prop.IsDefined(typeof(LengAttribute), true))
//{ // LengAttribute attribute = (LengAttribute)prop.GetCustomAttribute(typeof(LengAttribute), true); // if (!attribute.Validate(prop.GetValue(obj))) // return false; //} }return false;
} }public class LongAttribute: AbstractValidateAttribute
{ private long _Min, _Max = 0; public LongAttribute(long min,long max) { this._Min = min; this._Max = max; }public override bool Validate(object value)
{ if(value!=null && !string.IsNullOrWhiteSpace(value.ToString())) { if( long.TryParse(value.ToString(), out long lResult)) { if (lResult > _Min && lResult < _Max) return true; }}
return false; } }public class LengAttribute : AbstractValidateAttribute
{ private long _Min, _Max = 0; public LengAttribute(long min, long max) { this._Min = min; this._Max = max; }public override bool Validate(object value)
{ if (value != null && !string.IsNullOrWhiteSpace(value.ToString())) { int length = value.ToString().Length; if (length > _Min && length < _Max) return true;}
return false; } }