说起反射,我们并不陌生,并且我在之前的博客中,http://blog.csdn.net/gaibian0823/article/details/44624423也已经提到过,一个是这里面提到的只是理解层面上的,二是反射一般很少自己出现,都是结合着其他知识点出现。所以这次不会再体现在理解层面上,我们从例子中看问题。
一、反射
反射就是在我们不去引用另外一个程序集或者模块,而直接调用他的属性、方法。
1.首先是这个程序,我要在Program中调用User中的属性以及方法。
2.类User中的代码:
<span style="font-family:KaiTi_GB2312;font-size:18px;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ITOO_DAL { public class User { //字段 public string Field = "Hello World"; //属性 public string Name { get; set; } //无参构造 public User() { this.Name = "无参构造"; } //有参构造 public User(string UserName) { this.Name = UserName; } //public函数 public void publicFunction() { Console.WriteLine(string.Format("调用的是我public方法")); } //private函数 private void privateFunction() { Console.WriteLine(string.Format("调用的是我private方法")); } //static函数 public static void staticFunction() { Console.WriteLine(string.Format("调用的是我静态static方法")); } //public带参带返回值函数 public string publicFunctionPara(string UserName) { return string.Format("调用带参带返回值函数,参数为:{0}",UserName); } } } </span>3.主函数
<span style="font-family:KaiTi_GB2312;font-size:18px;">using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ITOO_Reflection { class Program { static void Main(string[] args) { //使用 Assembly 定义和加载程序集, //加载在程序集清单中列出的模块, //以及从此程序集中查找类型并创建该类型的实例. //获取程序集 Assembly assembly = Assembly.Load("ITOO_DAL"); //从程序集中获取指定对象类型; Type type = assembly.GetType("ITOO_DAL.User"); //方法一:创建类的实例 //使用Activator创建实例(无参数构造函数) var userNoParameter = Activator.CreateInstance(type); //使用Activator创建实例(带参数构造函数) var userParameter = Activator.CreateInstance(type, "wangjinbo"); //方法二:创建类的实例 //使用无参构造函数创建类(先反射创建构造函数,再使用构造函数创建类) ConstructorInfo constructorNoParameter = type.GetConstructor(new Type[] { }); var userNoParameterByConstructorInfo = constructorNoParameter.Invoke(new object[] { }); //使用有参构造函数创建类(先反射创建构造函数,再使用构造函数创建类) ConstructorInfo constructorParameter = type.GetConstructor(new Type[] { typeof(string) }); var userParameterByConstructorInfo = constructorParameter.Invoke(new object[] { "wangjinbo" }); //调用public函数(无参数) type.InvokeMember("publicFunction", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, userNoParameter, null); //调用public函数(带参数) string returnValuePublic = type.InvokeMember("publicFunctionPara", BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, userNoParameter, new object[] { "wangjinbo" }) as string; Console.WriteLine(returnValuePublic); //调用静态方法 string returnValueStatic = type.InvokeMember("staticFunction", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { }) as string; Console.WriteLine(returnValueStatic); //反射属性 var Name = type.InvokeMember("Name", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, userNoParameter, new object[] { }) as string; Console.WriteLine(Name); //设置属性(设置Name属性为"NewName") type.InvokeMember("Name", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, userNoParameter, new object[] { "NewName" }); //反射字段 string Field = type.InvokeMember("Field", BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance, null, userNoParameter, new object[] { }) as string; Console.WriteLine(Field); //设置字段(设置Field字段为"NewField") type.InvokeMember("Field", BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance, null, userNoParameter, new object[] { "NewField" }); } } } </span>上面就是通过反射从一个类中调用了另一个类中的属性以及方法。
二、反射+IOC容器
1.什么是IOC?
IOC即控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较广泛。
当然这是官方解释,我的解释是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
2.反射+依赖注入、依赖查找
首先,我们来看依赖注入:
通过get,set注入
然后直接使用D层所有方法:
2.依赖查找
配置文件中:
程序中,GetObject为反射:
依赖注入和依赖查找都用到了反射,但是依赖注入是被动的,依赖查找是主动的,依赖查找是需要来把配置文件中的id写进来,而注入get,set后,可以使用里面的所有方法。
总的流程就是:
1.加载配置文件中的所有内容。
2.将id,value放到一个哈希表中。
3.反射来查找id或者name,来调用相关类。
这些知识,我们用了很长时间,但是前面并不理解,所以我们需要更加主动地去整理总结这些知识,而不是被动地接受。