反射学习由浅入深
第一,引入:dll的引入方法 通过当前控制台应用程序的引用的添加(解决方案下的引用) 再到命名空间的引用(使用类中的引用)
首先,在解决方案下新建一个类库及一个控制台应用程序(类库可编辑成dll文件)【注类库与应用程序在同一解决方案同级下】
控制台应用程序代码为:
using myFeflectionDal.Dal;//SqlServerHelper命名空间的引用 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace myReflection { class Program { static void Main(string[] args) { //普通做法 创建对象的方法 SqlServerHelper ss = new SqlServerHelper(); ss.Query(); } } }
类库代码为:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace myFeflectionDal.Dal { //public class SqlServerHelper:IHelper 定义接口后的类写法(接口在下面)
public class SqlServerHelper { public SqlServerHelper() { Console.WriteLine("这里开始SqlServerHelper构造函数"); } public void Query() { Console.WriteLine("SqlServerHelper Query"); Console.ReadKey(); } } }
执行的顺序为:先执行构造函数再在执行普通方法。输出结果的顺序为:先:这里开始SqlServerHelper构造函数 后: SqlServerHelper Query
通过对象掉用。
第二,通过反射动态加载dll文件 使用类中:使用命名空间 using System.Reflection
反射就是通过某种事物去反射另一种事物;我们小时候进行喜欢用镜子对着墙上照,会出现一个个小光圈,这就是很典型的反射例子,我们把它理解成计算机里的反射就是我用某中对象去反射我无法直接获取到的东西。
控制台应用程序中的代码: 注意:编译后需将所需的dll文件复制到当前项目的bin目录下然后调用,而不需要在解决方案下引用
1.得到名称
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; //反射核心命名空间 namespace myReflection { /// <summary> /// (元数据)metadata+中间语言 =编译后 元数据(metadata)只用通过反射得到 /// </summary> class Program { static void Main(string[] args) { Assembly assembly= Assembly.Load("myFeflectionDal.Dal");//动态加载dll文件 动态解析 动态使用 Module[] modules = assembly.GetModules();//GetModules() 获取作为此程序集的一部分的所有模块。
//////////////////////Assembly 下面有很多东西,比如GetModules 。。。 foreach (Module module in modules) { Console.WriteLine(module.Name); } } } }
//功能为:打印当前dll文件的名称 模块的
打印结果为:myFeflectionDal.Dal.dll
获取产生dll文件的类型(dll来源)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; using myReflection.Interface; namespace myReflection { /// <summary> /// (元数据)metadata+中间语言 =编译后 /// </summary> class Program { static void Main(string[] args) { Assembly assembly= Assembly.Load("myFeflectionDal.Dal");//动态加载dll文件 Console.WriteLine("----------dll文件产生的类型(来源)--------------------------"); Type[] types = assembly.GetTypes();//dll里面所有类型 foreach (Type type in types) { Console.WriteLine(type.Name);//打印dll的类型 } Type typeHelper = assembly.GetType("myFeflectionDal.Dal.SqlServerHelper");//带命名空间 object oHelper= Activator.CreateInstance(typeHelper); //此时无法调用SqlServerHelper类里面的方法 所以考虑将SqlServerHelper类里面的方法抽象成接口 IHelper iHerper = (IHelper)oHelper; iHerper.Query(); } } }
IHelper接口定义:
using System; namespace myReflection.Interface { public interface IHelper { void Query(); } }
总结:普通的通过创建对象 的方式来调用方法(Query) 调用了构造函数,使用反射的方式来创建的对象也同样调用了构造函数。但是此时创建的对象是object 类型,无法去调用SqlServerHelper 类下面的Query方法,需要将SqlServerHelper 类下面的Query方法抽象成接口,然后SqlServerHelper类继承础接口,之后将object类型强转成接口类型,最终就可以通过接口类型去调用方法。
普通对象创建new《=》反射:(1)Module()+(2)Type()+ 【object oHelper= Activator.CreateInstance(typeHelper);】两个过程都调用构造函数创建了对象,但是类型不一样。
特别注意: 使用反射不需要添加需要使用的dll文件的引用,只需将需要的dll文件拷贝到当前项目的bin目录下。之后通过反射方法获取使用。当需要使用的dll文件修改后,需重新生成该文件,再拷贝到需要使用该文件的bin目录下。
最终总结:
代码为(通过配置文件来配置字符串)
配置文件的使用:
第一需要在解决方案的使用项目中添加引用(System.Configuration)
第二在使用类中添加命名空间(using System.Configuration)
第三,在具体的Web.config中添加配置
<appSettings> <add key="Ihelper" value="myFeflectionDal.Dal,myFeflectionDal.Dal.SqlServerHelper"/> </appSettings>
使用配置文件后的代码为:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; using myReflection.Interface; using System.Configuration;//配置文件核心命名空间 namespace myReflection { /// <summary> /// (元数据)metadata+中间语言 =编译后 /// </summary> class Program { static void Main(string[] args) { Console.WriteLine("-------可配置可扩展------------"); string helpConfig = ConfigurationManager.AppSettings["Ihelper"]; Assembly assembly = Assembly.Load(helpConfig.Split(',')[0]);//动态加载dll文件 Type typeHelper = assembly.GetType(helpConfig.Split(',')[1]);//找出具体类型 object oHelper = Activator.CreateInstance(typeHelper);//创建对象 IHelper iHerper = (IHelper)oHelper;//转换对象 iHerper.Query();//通过对象调用方法 } } }
可配置:体现在只需要修改配置文件,就可以修改行为。
可扩展:体现在可增加配置节点 例如:数据库之间的切换使用