///
/// 特性:中括号声明
///
/// 错觉:每一个特性都可以带来对应的功能
///
/// 实际上特性添加后,编译会在元素内部产生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;
}
}