c#反射
写在前面:此随笔仅仅是作为个人学习总结,有不对的地方,请各位前辈指正O(∩_∩)O........
一: 什么是反射
运行时获取类型信息的方式,动态加载dll.通常我们的类库生成之后会生成两个文件一个dll一个pdb文件.其中pdb用于调试,dll又由两部分组成:IL和metadata(元数据).反射就是动态加载dll里面的元数据部分获取到信息.
二: 应用场景
只说一个.当我们只知道一个类型的名字,不知道所在的位置和具体信息的时候,我们可以通过反射技术来知道写这个类的程序员想让我们知道的内部的信息.来获取和使用
三: 具体操作
3.1: 通过反射获取到类信息,和实现程序的可配置
//使用反射 Assembly assembly = Assembly.Load("Reflection.One"); //生成assmbly对象,动态加载dll,是反射的入口 Type type = assembly.GetType("Reflection.One.Common"); //获取类型 object o = Activator.CreateInstance(type); //根据类型创建一个object对象,此时调用的是无参数的构造函数 ICommon oCommon = o as ICommon; //根据接口类型转换object对象 oCommon.Method1(); foreach(var module in assembly.GetModules()) //使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法 { Console.WriteLine(module); } foreach(var t in assembly.GetTypes()) //获取程序集中所有的类型 { Console.WriteLine(t); } //通过有参数构造函数来创建对象 object[] conParam = new object[] { "Joy" };//构造函数的参数列表 object o2 = Activator.CreateInstance(type1,conParam); ICommon oCommon2 = o2 as Common;
如何实现程序的可配置
//通过反射实现程序的可配置,通过类型来创建对象 string configSetting = ConfigurationManager.AppSettings["dll"]; string[] configArr = configSetting.Split(','); Assembly assembly1 = Assembly.Load(configArr[0]); Type type1 = assembly.GetType(configArr[1]); object o1 = Activator.CreateInstance(type1); ICommon oCommon1 = o1 as ICommon; oCommon1.Method1(); //配置文件 <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> </startup> <appSettings> <add key="dll" value="Reflection.One,Reflection.One.Common"/> </appSettings> </configuration>
a: 为什么说是程序的可配置?
答: 只需要修改配置文件,不需要修改任何程序就可以实现不同的内容,比如连接mysql数据库和sql server数据库.
3.2: 通过反射调用方法
通过反射调用方法?上面3.1里面的不是也可以调用方法吗?是的,但是3.1里面的我们需要知道他们实现了哪一个接口,如果不知道实现了哪个接口我们同样是不能知道怎么调用程序集内部的方法.
获取到方法:
foreach(var m in type.GetMethods()) { Console.WriteLine(m.Name); }
a: 为什么没有看到Method4呢?
答: 我们可以看到Method4方法是私有的,而我们获取方法的方式不能获取到私有方法.
b: tostring(),equals(),getHashCode(),getType()方法是哪里来的呢?
答: 我们可以知道object类是所有类型的父类,而object里面有这几个方法,就可以知道这几个方法是继承至object里面的
c: 怎么获取到私有方法呢?
答: MethodInfo method4 = type.GetMethod("Method4", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
d: 输出结果里面怎么有两个相同的method3呢?又怎么调用呢?
答: 显然这是一个重载方法. 怎么调用?在获取方法的时候我们可以通过参数列表来判断获取的是哪一个方法,然后再来调用
MethodInfo method31 = type.GetMethod("Method3", new Type[] { }); //无参数 method31.Invoke(o2, null); //调用 MethodInfo method32 = type.GetMethod("Method3", new Type[] { typeof(int)}); // 有个int参数 method32.Invoke(o2, new object[] { 1}); //调用,new object[] 为参数列表