特性初步认识:
[Obsolete]、[Serializable]等
1. 被废弃的,可以影响编译器的运行!
2. 可以序列化和反序列化,可以影响程序的运行!
MVC [filter]过滤器
ORM [table]、[key]、[display]
WCF
特性初步了解:
1. 中括号声明,每一个特性都可以带来对应的功能。
2. 影响编译器的运行,影响程序运行。
3. 就是一个类,继承自attribute。(直接/间接继承都可以)
4. 一般以Attribute结尾,声明时可以省略掉。
实际上,特性添加后,编译会在元素的内部产生IL,但是我们是没有办法直接使用的,而且在metadata(元数据)里面会有记录。
1 | [//AttributeUsage用来修饰特性的特性 ] |
1 | [//特性无参数的构造函数 ] |
1 | [//特性也可以修饰方法 ] |
以上为特性的语法。
特性有什么用?特性有什么价值?
特性:是用于在运行时传递程序中的各种元素(比如类、方法、结构、枚举、组建等)的行为信息的声明性标签。
可以通过使用特性想程序添加声明性信息。
一个声明性标签是通过放置在它所应用的元素前面的方括号([])来描述的。
特性作用:用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。
.Net框架提供了两种类型的特性:预定义特性和自定义特性。
预定义特性:
** AttributeUsage **修饰特性的特性
** Conditional **这个预定义特性标记了一个条件方法,其执行依赖于指定的预处理标识符。
** Obsolete **标记了不应被使用的程序实体。(过时的)
在程序运行的过程中能找到特性。
Unity中特性的应用!
特性类似于类的补充。增加类额外的信息和行为!(没有破坏类的封装的前提下,没有修改类)
利用反射找特性
通过反射获取特性的方法
01. 通过反射获取类型,检查该类型有没有被特性(CustomAttribute)修饰。
1 | Type type = typeof(Student); //student.GetType(); //01.通过反射获取类型 |
02. 通过反射获取属性,检查该属性有没有被特性(CustomAttribute)修饰。
1 | PropertyInfo property = type.GetProperty("Id"); |
03. 通过反射获取方法,检查该方法有没有被特性(CustomAttribute)修饰。
1 | MethodInfo method = type.GetMethod("Answer"); |
04. 通过反射获取方法参数,检查该参数有没有被特性(CustomAttribute)修饰。
1 | MethodInfo method = type.GetMethod("Answer"); |
05. 通过反射获取方法的返回值,检查该返回值有没有被特性(CustomAttribute)修饰。
1 | MethodInfo method = type.GetMethod("Answer"); |
总的集合代码:
1 | public static void Show(Student student) |
1 | [//AttributeUsage用来修饰特性的特性 ] |
1 | [ ] |
任何一个生效的特性,都是有地方使用了他。
特性的应用场景:
01、给枚举项加一个描述。
02、实体类的属性也可以Display。
03、别名,有特性以特性名称为准,没有特性以枚举类型名称为准。 这种形式称之为映射。
04、做数据检查(可以写在数据库保存之前,或保存方法中)
05、假如属性很多,尝试反射+特性使用
框架的思想
应用场景01: 枚举的应用
** **根据不同的枚举值,触发不同的逻辑
1 | public enum UserState //用户状态 |
1 | UserState userState = UserState.Normal; |
原来的书写方式,也能解决问题,但是不太推荐。
1 | public enum UserState //用户状态 |
1 | UserState userState = UserState.Normal; |
应该用更高级的写法,应该用特性:
1 | public enum UserState |
1 | public class RemarkAttribute : Attribute |
1 | public static class RemarkExtension |
1 | UserState userState = UserState.Normal; |
进一步优化,得到
1 | Console.WriteLine(UserState.Frozen.GetRemark()); |
代码里书写是英文,(打印出来显示)或逻辑前端需要显示的是中文。
应用场景归纳:
实质:给枚举项加一个描述。书写了一个规则!
01. 实体类的属性也同样可以!Display的应用。MVC中语法已经支持了!
02. 数据库查询一个列表,列名称(ID/账号/密码/登录时间)(name/pwd/dataTime/… …)
03. 别名,映射!
类似于类的补充,添加一些额外的行为!
做数据检查(可以写在数据库保存之前,保存方法里面也可) ****
1 | public class Student |
QQ的限制范围,曾经的方式:
1 | if (student.QQ > 10001 && student.QQ < 999999999999) |
解决数据合法性的问题,数据的检查,重复性比较高!
1 | private long _QQ2 = 0; //解决数据合法性,但是给属性增加了太多的事儿,后面更改容易抛出异常! |
实体映射数据库!逻辑单一性原则!
1. 首先自定义一个特性
1 | public abstract class AbstractValidateAttribute : Attribute //抽象类 |
1 | public class LongAttribute : AbstractValidateAttribute |
1 | public class Student |
** 验证的拓展类 **
1 | public static class ValidateExtension |
进一步深入拓展可用改造成
1 | public abstract class AbstractValidateAttribute : Attribute //抽象类 |
1 | [//自定义特性的特性修饰 ] |
1 | public class LongAttribute : AbstractValidateAttribute //继承抽象类,重写方法,来具体实现 |
1 | public static class ValidateExtension //改造后的验证拓展类,只要验证的特性基于AbstractValidateAttribute(抽象验证特性类),那么这个ValidateExtension则不需要更改了。 |
1 | public class Manager |
抽象类/继承/具体实现,具体的使用方式。需要深入拓展一下!
特性和配置文件很像!方便维护!
作业练习:
···数据库映射/泛型的数据库访问方法。
···合理自定义接口并使用。
···异常处理/调试技巧等。
···自定义封装框架。
- 本文作者: 梁俊可
- 本文链接: http://ljk3d.com/2021/10/19/cSharpNote/CSharp高级进阶教程_03_特性/
- 版权声明: 梁俊可工作室