反射概念:
.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,程序集包含模块 模块包含类型,类型又包含
成员,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息, .NET Framework提供命名空间System.Refection和
System.Type,可以获取已加载的程序集和程序集中定义的类型(类、接口、值类型)的信息也可以使用反射在运行时创建类型实例,将类型绑定到现有
对象,或主从现有对象中获取类型,调用和访问这些实例
练习示例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Business; namespace FirstReflection { public class ComputerFactory : IMessageHandler { //品牌 public string brand { get; set; } //地址 public string address { get; set; } /// <summary> /// 构造函数 /// </summary> public ComputerFactory() { } /// <summary> /// 构造函数 /// </summary> /// <param name="brand"></param> public ComputerFactory(string brand,string address) { this.brand = brand; this.address = address; } public void displayBrand() { Console.WriteLine(this.brand); } public void displayaddress(string address) { Console.WriteLine("public:生产地址:{0}",address); } public static void displayaddress() { Console.WriteLine("public static共有方法:生产地址:本部"); } private void privatedisplayaddress(string address) { Console.WriteLine("private私有方法:生产地址:{0}", address); } } }
通过Assembly类的load()方法加载程序集,并在程序集中查找定义的类型......
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; namespace FirstReflection { /*反射: 1.获取方法的信息 2.调用方法 3.构造对象 4.从程序集中加载类型 */ public class Program { //查看程序集中所有的类 public static void ShowClassName(Type[] types) { Console.WriteLine("查看程序集中所有的类:"); foreach (Type type in types) { Console.WriteLine(type); } } public static void ShowModuleName(Module[] modules) { Console.WriteLine("查看程序集中所有的模块:"); foreach (Module module in modules) { Console.WriteLine(module); } } public static void ShowPropertyName(PropertyInfo[] properties) { Console.WriteLine("查看该类型的属性:"); foreach (PropertyInfo property in properties) { Console.WriteLine(property); } } static void Main(string[] args) { //[0] //加载程序集 Assembly assembly = Assembly.Load("FirstReflection"); //Assembly assembly = Assembly.LoadFrom("FirstReflection.exe"); //[1]:查看程序集中所有的类 Type[] types = assembly.GetTypes(); ShowClassName(types); //[2]:查看模块 Module[] modules = assembly.GetModules(); ShowModuleName(modules); //[3]:取得类类型 Type getType = assembly.GetType("FirstReflection.ComputerFactory"); Type getTypeTwo = Type.GetType("FirstReflection.ComputerFactory"); //Console.WriteLine(getType);//输出:FirstReflection.ComputerFactory //[4]:查看该类的属性 PropertyInfo[] properties = getType.GetProperties(); ShowPropertyName(properties);//protected、private 属性未获取到 //[5]:查看实现的接口 Type[] iTypes = getType.GetInterfaces(); Console.WriteLine("查看继承的接口:"); foreach (var item in iTypes) { Console.WriteLine(item.Name); } //[6]:查看类的所有方法(只获取public方法) ***** /*【get;set访问器也会被解析】*/ MethodInfo[] methods = getType.GetMethods(); Console.WriteLine("查看类的所有方法:"); foreach (var item in methods) { Console.WriteLine(item); } //[6-2]:查找public方法 与getType.GetMethods()返回结果一样 MethodInfo[] publicMethods = getType.GetMethods(BindingFlags.Instance | BindingFlags.Public); Console.WriteLine("查看类的public方法:"); foreach (var item in publicMethods) { Console.WriteLine(item); } //[6-1]:查找私有方法(protected、private) //NonPublic指反射,但找到的属性/特性是NonPublic访问的 //Instance 只是找到实例的引用对象,类似c++中的实例句柄指针(当然这个是枚举类型) MethodInfo[] nonPublicMethods = getType.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); Console.WriteLine("查看类的私有方法:"); foreach (var item in nonPublicMethods) { Console.WriteLine(item); } //[7]:获取构造函数 ConstructorInfo[] constructors = getType.GetConstructors(); Console.WriteLine("查看类的够着方法:"); foreach (var item in constructors) { Console.WriteLine(item); } //[8]:创建实例 //方法1(有问题) object IBMcomputer = Assembly.GetAssembly(getType).CreateInstance("ComputerFactory"); //方法2 object[] constructParam = new object[] { "HP","北京" }; //带参数 object HPcomputer = Activator.CreateInstance(getType, constructParam); //不带参数 object HPcomputer2 = Activator.CreateInstance(getType, null); //[9]:使用反射调用方法(public方法) foreach (MethodInfo m in publicMethods) { if (m.Name == "displayaddress") {//调用public void displayaddress(string address)() object[] Param = new object[] { "北京" }; m.Invoke(HPcomputer2, Param); } } //[9-1]:使用反射调用方法 (NonPublic 方法) MethodInfo met = getType.GetMethod("privatedisplayaddress", BindingFlags.Instance | BindingFlags.NonPublic); object[] Param2 = new object[] { "北京" }; met.Invoke(HPcomputer2, Param2); //[9-*]其他 Console.ReadLine(); } } }
查看结果:
其中:查看类的所有方法出现 get_brand(), set_brand() 说明 get/set访问器在编译时 生成的公有方法get_brand(), set_brand()
步骤:
1.加载程序集 使用Assembly类的Load()或者LoadFrom()方法加载程序集,区别是后者需要加入程序集的后缀名,例如.DLL .exe
2.找到相应的命名空间+类 Type类型也是抽象类,只能通过GetType()或者typeof()来实现
3.获取类的方法 getMethod() 根据需要调用的方法的访问级别 public protected privat 及static传入相应的参数 方法名+ (BindingFlags.Instance | BindingFlags.Public)等
4.调用方法 MethodInfo.Invoke() 传入实例,方法的参数