今天我们就来说一说反射(Reflection ),
反射是什么呢?反射是动态获取程序集的元数据(metadata)的一种技术。反射是.NetFramework类库提供的帮助类,动态加载dll实现程序的可配置可扩展。
首先我们来看一个简单的实现反射的例子,我们先创建整个框架
IDAL里面是一个接口,接口里面有一个Query方法,
using System; namespace Reflect.IDAL { public interface IHelper { void Query(); } }
假设这个Query方法就是链接数据库的某个方法,下面我们就实现它
现在有一个sqlserver数据库,我们要写DAL数据Helper类来实现
using Reflect.IDAL; using System; namespace Reflect.DAL { public class SqlServerHelper : IHelper { public SqlServerHelper() { Console.WriteLine("这是SqlHelper的构造函数"); } public void Query() { //throw new NotImplementedException(); Console.WriteLine("这是一个假的实现sqlhelp的方法"); } } }
假设我们现在链接了数据库,然后我们就需要在控制台输出一下,在控制台实现之前,我们就要配置一下,反射就是为了实现可配置的嘛。
打开app.Config 添加appSetting节点如下
<appSettings> <!--<add key="DAL" value="Reflect.DAL,Reflect.DAL.SqlServerHelper"/>--> <add key="DAL" value="Reflect.MySql.DAL,Reflect.MySql.DAL.MySqlHelper"/> </appSettings>
这里有两个key,第一个是sqlServer链接的配置,第二个是MySql的链接配置,sqlServer的配置被注释了,我们实现的也就是mysql的配置,mysql的DAL的代码和sqlServer的类似。
using Reflect.IDAL; using System; namespace Reflect.MySql.DAL { public class MySqlHelper : IHelper { public MySqlHelper() { Console.WriteLine("这是MySqlHelper的构造函数"); } public void Query() { Console.WriteLine("这是一个假的实现MySqlHelper的方法"); } } }
这个也就是反射的已扩展,当所有的类定义好以后需要扩展不需要修改实现的代码,下面就是控制台的代码
using Reflect.DAL; using Reflect.IDAL; using System; using System.Configuration; using System.Reflection; namespace Reflection { class Program { static void Main(string[] args) { Console.WriteLine("****************从这里开始反射*************"); //SqlServerHelper sqlhelper = new SqlServerHelper(); //sqlhelper.Query(); string HelperConfig = ConfigurationManager.AppSettings["DAL"].ToString(); Assembly assenbly = Assembly.Load(HelperConfig.Split(‘,‘)[0]);//动态的加载dll Type typeHelper = assenbly.GetType(HelperConfig.Split(‘,‘)[1]);//找出具体的类型 object oHelper = Activator.CreateInstance(typeHelper);//创建对象等同于new IHelper ihelper = (IHelper)oHelper;//将object类型转换为接口类型 ihelper.Query(); Console.ReadKey(); } } }
//SqlServerHelper sqlhelper = new SqlServerHelper(); //sqlhelper.Query();
这里被注释的两行代码其实也能实现,而且是我们平常实现的常用做法,可是他的局限性就是在扩展方面需要修改代码,而我们在编写程序的时候所要求的是对扩展开放,对修改密封,这里他就不太好用了。当上面所有的实现之后,我们运行程序
我们要是想要更换数据库,只要修改配置文件,不需要修改代码就能实现,是不是好了很多。
<appSettings> <add key="DAL" value="Reflect.DAL,Reflect.DAL.SqlServerHelper"/> <!--<add key="DAL" value="Reflect.MySql.DAL,Reflect.MySql.DAL.MySqlHelper"/>--> </appSettings>
使用反射的优缺点优点:
优点:反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类;
缺点:(1)性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
(2)使用反射会模糊程序内内部逻辑:程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。
我们需要在使用反射的时候一定要明确反射的有缺点,这样才能让程序更加完善。