学习笔记:C#高级进阶语法——特性(Attribute)
1.学习笔记:C#高级进阶语法——反射(Reflection)2.学习笔记:C#高级进阶语法——泛型(Generic)
3.学习笔记:C#高级进阶语法——特性(Attribute)
4.学习笔记:C#高级进阶语法——委托(Delegate)三、特性(Attribute)
3.1、特性的本质
什么是特性?
特性本质是一个类,直接或间接的继承自抽象类Attribute,可以把这个类,用[类名]进行注册标记到类似及类内部的所有成员:约定俗成,默认以Attribute结尾,在进行标记的时候,如果特性类是Attribute结尾的,可以省略不写结尾的Attribute。
特性的约束?
[AttributeUsage(AttributeTargets.All,AllowMultiple = true,Inherited = true)],用来约束特性的特性,AttributeTargets约束用途,AllowMultiple 为true的时候,表示这个特性可以在一个类或者属性等上重复标记,Inherited = true表示这个特性可以被继承。
3.2、特性和注释的区别
注释在编译器编译后是不存在的
3.3、特性的调用
{ //标记好的特性要如何调用? //要调用特性,必须用到反射 //1、使用反射 //两种方式都可以 Type type = student.GetType(); //Type type = typeof(Student); //2、获取特性实例,标准用法---先判断,再获取实例 if (type.IsDefined(typeof(CustomAttribute), true)) { CustomAttribute customAttribute = type.GetCustomAttribute<CustomAttribute>();//执行特性的构造函数 } //获取属性上的特性 foreach (var prop in type.GetProperties()) { if (prop.IsDefined(typeof(CustomAttribute), true)) { CustomAttribute attribute = prop.GetCustomAttribute<CustomAttribute>(); } } //获取字段上的特性 foreach (var field in type.GetFields()) { if (field.IsDefined(typeof(CustomAttribute), true)) { CustomAttribute attribute = field.GetCustomAttribute<CustomAttribute>(); } } //获取方法上的特性 foreach (var mehtod in type.GetMethods()) { if (mehtod.IsDefined(typeof(CustomAttribute), true)) { CustomAttribute attribute = mehtod.GetCustomAttribute<CustomAttribute>(); } } //特性是一个类,获取到一个实例,--就是得到了一个类的实例 }
定义特性
namespace C_MyAttribute { [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)] public class CustomAttribute : Attribute { private int _Id { get; set; } public string _Name { get; set; } public int _Age; public CustomAttribute() { } public CustomAttribute(int id) { this._Id = id; } public CustomAttribute(string name) { this._Name = name; } public void Do() { Console.WriteLine("this is CustomAttribute"); } } public class ChildStudent : CustomAttribute { } }
标记特性
namespace C_MyAttribute { /// <summary> /// 这是一个Student类 /// </summary> // [Obsolete("请不要使用这个了,请使用什么来代替",true)]//系统 --在之前--标记的这玩意还可以影响编译器 //; [Serializable]//可以序列化和反序列化 --类标记了这个特性以后,就可以做序列化 [Custom(id: 234)] //不允许标记两个 对应的无参数构造函数 [Custom] //标记到类 public class Student { /// <summary> /// /// </summary> [Custom(1234)] //标记到属性 public int Id { get; set; } public string Name { get; set; } [CustomAttribute("Richard")] //标记到字段 public string Description; [CustomAttribute(_Age = 30)] //标记到方法 public void Study() { Console.WriteLine($"这里是{this.Name}跟着Eleven老师学习"); } /// <summary> /// 提问 /// </summary> /// <param name="name"></param> /// <returns></returns> [return: CustomAttribute] //标记到方法的返回值 public string Answer([CustomAttribute] string name) // [CustomAttribute] //标记到方法的参数 { return $"This is {name}"; } [CustomAttribute] //标记到委托 public delegate void StudentDelegate(); //索引器 [CustomAttribute] //标记到索引器 public Index[] values; } }
3.4、特性的价值
特性到底可以带来什么? 1.特性可以提供额外信息----本来不具备这个信息的,可以通过特性来增加 2.特性可以提供额外功能----本来不具备这个功能的,可以通过特性来支持这个功能
实例:我定义了一个枚举用来表示用户状态,但是他们的中文含义无法定义,需要在使用的时候,用if去判断输出
namespace C_MyAttribute { public enum UserStateEnum { /// <summary> /// 正常 /// </summary> Normal = 0, /// <summary> /// 已冻结 /// </summary> Frozen = 1, /// <summary> /// 已删除 /// </summary> Deleted = 2 } }
UserInfo userInfo = new UserInfo() { Id = 1, Name = "Seven", Age = 20, Mobile = "18888888888", State = UserStateEnum.Normal }; { //原始做法,根据枚举来判断,得到中文状态 if (userInfo.State == UserStateEnum.Normal) { Console.WriteLine("用户状态为正常"); } else if (userInfo.State == UserStateEnum.Frozen) { Console.WriteLine("用户状态为已冻结"); } else if (userInfo.State == UserStateEnum.Deleted) { Console.WriteLine("已删除"); } //多个页面要使用,则都要做判断 }
如何利用特性来扩展他,让我在得到状态的时候,就可以知道它的中文注释
1、定义特性
namespace C_MyAttribute.Extend { /// <summary> /// 状态描述 /// </summary> [AttributeUsage(AttributeTargets.Field)] public class RemarkAttribute : Attribute { private string _Desctiption; public RemarkAttribute(string desctiption) { _Desctiption = desctiption; } public string GetDescription() => _Desctiption; } }
2、在枚举上面标记特性
using C_MyAttribute.Extend; namespace C_MyAttribute { public enum UserStateEnum { /// <summary> /// 正常 /// </summary> [Remark("正常")] Normal = 0, /// <summary> /// 已冻结 /// </summary> [Remark("已冻结")] Frozen = 1, /// <summary> /// 已删除 /// </summary> [Remark("已删除")] Deleted = 2 } }
3、封装调用
using C_MyAttribute.Extend; using System.Reflection; namespace C_MyAttribute { public class DescriptionManager { public static string GetDescription(object oValue) { Type type = typeof(UserStateEnum); FieldInfo field = type.GetField(oValue.ToString()); if (field.IsDefined(typeof(RemarkAttribute), true)) { RemarkAttribute attribute = field.GetCustomAttribute<RemarkAttribute>(); string description = attribute.GetDescription(); Console.WriteLine(description); return description; } else { return oValue.ToString(); } } } }
//使用 Console.WriteLine(DescriptionManager.GetDescription(userInfo.State));
对特性的方式进行升级优化
将封装的调用定义为扩展方法,并且限定传入的参数为枚举类型
using C_MyAttribute.Extend; using System.Reflection; namespace C_MyAttribute { public static class DescriptionManager { /// <summary> /// 静态类中的静态方法,同时第一个参数用this修饰,叫扩展方法 /// </summary> /// <param name="oValue"></param> /// <returns></returns> public static string GetDescription(this Enum oValue) { FieldInfo field = oValue.GetType().GetField(oValue.ToString()); if (field.IsDefined(typeof(RemarkAttribute), true)) { RemarkAttribute attribute = field.GetCustomAttribute<RemarkAttribute>(); string description = attribute.GetDescription(); Console.WriteLine(description); return description; } else { return oValue.ToString(); } } } }
对实体中增加一个属性,直接获取枚举对应的中文注释
namespace C_MyAttribute { public class UserInfo { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public long QQ { get; set; } public string Mobile { get; set; } /// <summary> /// 用户的状态 /// </summary> public UserStateEnum State { get; set; } public string StrDescription { get { return this.State.GetDescription(); } } } }
{ UserInfo userInfo1 = new UserInfo() { Id = 1, Name = "Seven", Age = 20, Mobile = "18888888888", State = UserStateEnum.Normal }; Console.WriteLine(userInfo1.StrDescription); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!