C#语言基础-15 反射
反射
自定义特性允许把自定义元数据与程序元素关联起来,这些元数据是在编译过程中创建的,并嵌入到程序集中。反射描述了在运行过程中检查和处理程序元素的功能。
反射允许:枚举类型成员、实例化新对象、执行对象成员、查找类型信息、查找程序集信息、检查类型的自定义特性、创建和编辑新程序集。
自定义特性
编写自定义特性
自定义特性类直接或间接的派生自System.Attribute类。特性类一般以Attribute结尾。在vs中创建自定义特性时,名称会自动追加Attribute,在使用时不需要写完整名称,如TestAttribute在使用时写Test或者TestAttribute都可以,匹配的都是TestAttribute类。当同时定义TestAttribute和TestAttributeAttribute时,使用TestAttribute时,编译器会报错,因为不知道引用的是哪个特性类。
特性类还需要指定:
特性可以应用到哪些类型的程序元素上(类、结构、属性和方法等)、
是否可以多次应用到同一个程序元素上、
应用到类或接口上时,是否由派生类和接口继承、
特性包含哪些必选和可选参数等。
指定AttributeUsage特性
该特性只能应用在其他特性上,用来标示自定义特性可以应用到哪些类型的程序元素上。该参数是必选的AttributeUsage特性的两个参数:都是可选的
AllowMultiple:标示是否可以多次应用到同一项上。默认值false
Inherited:标示应用到类或接口上时,是否由派生类和接口继承。应用到方法或属相上时,是都可以重写版本。默认值true
指定特性参数
编译器会检查传递给特性的参数,并查找该特性中带这些参数的构造函数。如果找不到就会抛出异常。
指定特性的可选参数
可以通过特性类中的公共属性或字段实现把可选参数添加到特性中。
[Test("", Num = 12)]//错误的,标示了只能应用于方法 class Program { [Test("", Num = 12)] static void Main(string[] args) { Person p = new Person() { Name = "Liu" }; Console.ReadKey(); } } //AttributeTargets.Method表示特性只能应用于方法,AllowMultiple=true表示可以引用1次或多次 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] class TestAttribute : Attribute { public int Num { get; set; }//使用公共属性接受可选参数 private string Show { get; set; } public TestAttribute(string show, string show2 = "")//使用构造函数参数接受必填参数 { Show = show; } }
反射
通过System.Type类可以访问关于任何数据类型的信息。通过System.Reflection.Assembly类可以访问给定程序集的相关信息。
System.Type类
Type类是一个抽象的基类。实例化Type对象时,实际上是实例化了Type的一个派生类。
获取给定类型的Type引用有3中方式
typeof运算符
GetType()方法。所有类都会从System.Object继承这个方法
使用Type类的静态GetType()方法。
Person p = new Person() { Name = "Liu" }; Type type = typeof(Person); type = p.GetType(); type = Type.GetType("Person");
Type的属性
获取包含与类相关的各种名称的字符串。
获取Type对象的引用,这些引用表示相关的类。
表示Type对象的一些属性。如IsClass、IsArray、IsEnum、IsAbstract、IsSealed、IsPublic等
Person p = new Person() { Name = "Liu" }; Type type = typeof(Person); var n = type.Name;//Person var fn = type.FullName;//ConsoleApp1.Person var ns = type.Namespace;//ConsoleApp1 Type bt = type.BaseType; Type ut = type.UnderlyingSystemType; bool isclass = type.IsClass;//true bool isenum = type.IsEnum;//false bool isarray = type.IsArray;//false bool ispublic = type.IsPublic;//false bool isabstract = type.IsAbstract;//false
Type的方法
大多数方法用于获取对应数据类型的成员信息:构造函数、属性、方法和事件等。
System.Reflection.Assembly类
Assembly类允许访问给定程序集的元数据,还包含可以加载和执行程序集的方法。
使用Assembly实例时,需要先把相应的程序集加载到正在运行的进程中。可以使用静态成员Assembly.Load()或Assembly.LoadFrom()。
Assembly.Load()的参数是程序集的名称。运行库会在各个位置搜索该程序集,包括本地目录和全局程序集缓存。
Assembly.LoadFrom()的参数是程序集的完成整路径名。
Assembly assembly = Assembly.Load("Newtonsoft.Json"); Assembly assembly2 = Assembly.LoadFrom(@"E:\LiuXiansheng\ConsoleApp1\bin\Debug\Newtonsoft.Json");
获取在程序集中定义的类型的详细信息
Assembly.GetTypes()方法可以返回程序集中定义的所有类型的详细信息的System.Type引用数组。
获取自定义特性的详细信息
Assembly.GetCustomAttributes()方法可以获取程序集或类型中关联的自定义特性。