特性
大约 6 分钟约 1814 字
特性
什么是特性,特性的本质
Serializable:只要是标记Serializable,就可以序列化
Serializable:还可以影响我们这个编译器
特性和注释的区别---看看特性的本质
如何自定义特性,特性的多种标记
如何调用到特性内部的成员--自定义的这个特性,如果才能使用它呢
{
Student student = new Student()
{
Id = 123,
Name = "我与春风皆过客"
};
//student.custom//调用不到
InvokeAttributeManager.Show(student);
}
{
public class InvokeAttributeManager
{
/// <summary>
/// 通过反射来调用特性---确实是可以调用到特性的实例的
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
public static void Show(Student student)
{
//Type type = typeof(Student);
Type type = student.GetType();
//1.先判断是否有特性
if (type.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in type.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
//获取当前Type下所有的属性上标记的特性
foreach (PropertyInfo prop in type.GetProperties())
{
if (prop.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in prop.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
}
//获取当前Type下所有的字段上标记的特性
foreach (FieldInfo field in type.GetFields())
{
if (field.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in field.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
}
//获取当前Type下所有的方法上标记的特性
foreach (MethodInfo method in type.GetMethods())
{
foreach (ParameterInfo para in method.GetParameters())
{
if (para.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in para.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
}
if (method.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in method.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
}
}
}
}
特性获取额外信息
{
//一、传统方式获取枚举
{
//UserStateEnum userState = UserStateEnum.Normal;
////1.传统方式如果要获取到描述--只能一层一层的判断
////2.你们觉得这样好吗?
////问题:
//// a.分支判断太多了--如果增加一个枚举字段---就需要增加一个判断
//// b.如果说描述信息改了呢?只要是是使用到这个枚举的地方--都需要修改这个描述信息----工作量剧增
//if (userState == UserStateEnum.Normal)
//{
// Console.WriteLine("正常状态");
//}
//else if (userState == UserStateEnum.Frozen)
//{
// Console.WriteLine("已冻结");
//}
}
//....
//二.通过特性来获取描述信息---额外信息--特性获取额外信息
{
//1.特性获取描述信息---获取额外信息
//好处:
// a.如果增加字段,就可以直接获取不用其他的改动
// b.描述修改后,获取描述信息的方法不用修改
//2.通过反射+特性+扩展方法,可以封装一个获取额外新的的公共方法
{
UserStateEnum normal = UserStateEnum.Normal;
UserStateEnum frozen = UserStateEnum.Frozen;
UserStateEnum deleted = UserStateEnum.Deleted;
UserStateEnum other = UserStateEnum.Other;
UserStateEnum other1 = UserStateEnum.Other1;
string strnormalRemark = RemarkAttributeExtension.GetRemark(normal);
string strfrozenRemark = RemarkAttributeExtension.GetRemark(frozen);
string strdeletedRemark = RemarkAttributeExtension.GetRemark(deleted);
string strotherRemark = RemarkAttributeExtension.GetRemark(other);
string strother1Remark = RemarkAttributeExtension.GetRemark(other1);
}
{
UserStateEnum normal = UserStateEnum.Normal;
UserStateEnum frozen = UserStateEnum.Frozen;
UserStateEnum deleted = UserStateEnum.Deleted;
UserStateEnum other = UserStateEnum.Other;
UserStateEnum other1 = UserStateEnum.Other1;
string strnormalRemark = normal.GetRemark();
string strfrozenRemark = frozen.GetRemark();
string strdeletedRemark = deleted.GetRemark();
string strotherRemark = other.GetRemark();
string strother1Remark = other1.GetRemark();
}
{
// //从数据库中查询出来一条数据;
UserInfo user = new UserInfo()
{
Id = 1234,
Name = "暖风昔人",
Age = 25,
State = UserStateEnum.Normal
};
Console.WriteLine($"当前用户的状态为:{user.UserStateDescription}");
UserInfo user1 = new UserInfo()
{
Id = 1234,
Name = "暖风昔人",
Age = 25,
State = UserStateEnum.Frozen
};
Console.WriteLine($"当前用户的状态为:{user1.UserStateDescription}");
UserInfo user2 = new UserInfo()
{
Id = 1234,
Name = "暖风昔人",
Age = 25,
State = UserStateEnum.Deleted
};
Console.WriteLine($"当前用户的状态为:{user2.UserStateDescription}");
//编程这事儿,代码写的精妙了以后,其实一门艺术;
}
}
}
特性获取额外功能--在之前的基础上,新增一个功能
{
//1.如果要保存一条数据到数据库中去
//2.从前端提交过来的数据格式为:
// {
// "id": 0,
// "name": "string",
// "age": 0,
// "state": 1
// }
//3.包含了很多字;
//4.如果数据库总Name的值要求存储的长度为40个字符--如果保存的数据超过40个字符---肯定会报错
//5.肯定要在保存之前就需要验证这行数据
//前端提交过来的数据
UserInfo adduse = new UserInfo()
{
Id = 123,
Name = "456464",
Age = 25,
Mobile = "sdfsdf"
};
//六-一
//1.传统方式:
//问题:
/// a. 太多的if判断
/// b. 代码量太多
{
if (adduse.Name == null)
{
Console.WriteLine("不能为空");
}
if (adduse.Name.Length > 40)
{
Console.WriteLine("Name超长了");
}
if (adduse.Mobile.Length != 11)
{
Console.WriteLine("手机号有问题");
}
}
//六--二//特性了获取额外功能---特性来完成验证
{
//增加了一个特性:可以对一个实体中的字段做验证-和验证不能为空
//1.通过特性加反射额外的获取了一个功能
//2.实体验证==特性获取额外信息+特性获取额外的来完成的
//好处:
//1.只要是把验证的规则特性定义好,就可以重新使用
//2.如果需要验证哪个属性,就把特性标记在哪个属性上就可以了;
//3.只是标记了一个特性,就可以获取了一个验证的逻辑
ApiResult bResult = ValidateInvokeManager.ValiDate<UserInfo>(adduse);
//验证一下QQ
//5位数---12位数
}
}
{
public static class ValidateInvokeManager
{
public static ApiResult ValiDate<T>(this T t) where T : class
{
//typeof(T);
Type type = t.GetType();
{
//#region 判断是否为空
//foreach (PropertyInfo prop in type.GetProperties())
//{
// if (prop.IsDefined(typeof(RequiredAttribute), true))
// {
// RequiredAttribute attribute = prop.GetCustomAttribute<RequiredAttribute>();
// object oValue = prop.GetValue(t);
// ApiResult result = attribute.Validate(oValue);
// if (result.Success == false)
// {
// return result;
// }
// }
//}
//#endregion
//#region 如果要判断长度
//foreach (PropertyInfo prop in type.GetProperties())
//{
// if (prop.IsDefined(typeof(LengthAttribute), true))
// {
// LengthAttribute attribute = prop.GetCustomAttribute<LengthAttribute>();
// object oValue = prop.GetValue(t);
// ApiResult result = attribute.Validate(oValue);
// if (result.Success == false)
// {
// return result;
// }
// }
//}
//#endregion
}
{
foreach (PropertyInfo prop in type.GetProperties())
{
if (prop.IsDefined(typeof(AbstractAttribute), true))
{
object oValue = prop.GetValue(t);
foreach (AbstractAttribute attribute in prop.GetCustomAttributes())
{
ApiResult apiResult = attribute.Validate(oValue);
if (apiResult.Success==false)
{
return apiResult;
}
}
}
}
}
//....
//如果还有更多的验证呢?难道每一个验证都这样写一下?
//抽象父类 特性 继承;
return new ApiResult() { Success = true };
}
}
}