反射与特性
特性的定义
特性用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,即可在运行时使用反射的技术查询特性。
特性的使用
1.特性作为编译器的指令时的应用
Obsolete(已过时特性):指某个程序实体建议标记为不在使用。两个参数第一个为显示的警告信息,第二个为是否导致编译器错误。省略第二个参数则为警告
Conditional(条件特性):依赖预处理标示符,通常用于在DEBUG标识符启用跟踪
DllImport:标记方法是在外部的dll中
2.自定义特性
例如
[AttributeUsage((AttributeTargets.Class|AttributeTargets.Struct),AllowMultiple=false,Inherited =true )] public class Author:Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } }
自定义特性类Author必须继承System.Attribute类。使用System.AttributeUsage来控制特性的应用范围它使得Author特性只能在Class和Struct声明中生效。AllowMultiple,Inherited 参数是可选的分别表示是否可应用多次和是否可继承。
3.使用特性
[Author("C#")] public class Book { //.... }
那么我们怎么将定义的特性在Book类中使用起来呢?这就要用到反射了。
反射的定义
Msdn上关于反射的定义是这样的:反射提供了描述程序集、模块和类型的对象(Type 类型)。 可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。 如果代码中使用了特性,可以利用反射来访问它们。
使用System.Type访问元数据
为了读取一个类型的元数据,首先得获得一个System.Type的实例。一般有三种方法获取
1.System.Object.GetType()
2.System.Type.GetType()
//命名空间加类名
3.Typeof操作符
显示结果
反射不仅可以获取元数据还可以获取已加载的程序集和在其中定义的类型(如类,接口,方法,属性。。。)也可以运用反射在运行时创建类型实例,以及调用和访问这些实例
例如:
将下面的代码编译为dll
public class Author { private string name; public double version; public Author() { } public Author(string name) { this.name = name; version = 1.0; } public void SayHello() { Console.WriteLine("Hello,World"); } }
通过反射来动态的调用dll
Assembly assembly = Assembly.LoadFile(@"G:\我的文档\资料文档\BlogsTemplate\DotNet基础\特性与反射\AtttriTest\ClassLibrary\bin\Debug\ClassLibrary.dll"); Type type = assembly.GetType("ClassLibrary.Author"); //namespace+className MethodInfo[] methodInfos = type.GetMethods(); Console.WriteLine("Author类中的方法"); foreach (var methodInfo in methodInfos) { Console.WriteLine(methodInfo.Name); } object obj = Activator.CreateInstance(type); Console.WriteLine("调用Author的SayHello方法"); MethodInfo method = type.GetMethod("SayHello"); method.Invoke(obj, null); Console.Read();
显示结果
反射在下列情况下很有用
1.当需要访问程序元数据的特性时
2.检查和实例化程序集中的类型
3.在运行时构建新类型
4.执行后期绑定,访问在运行时创建的方法
参考资料 MSDN