标签:
最开始接触反射是在机房收费系统中,是通过抽象工厂+反射防止更换数据库,在配置文件中定义好key—value,程序执行时根据key找到对应的value值,
配置文件代码:
<span style="font-size:18px;"> <appSettings> <add key ="assName" value ="DAL"/> <add key ="DB" value ="Sqlserver"/> </appSettings></span>
工厂层也通过配置文件中key—value拿到D层程序集和命名空间的名称,
工厂层代码:
<span style="font-size:18px;">Imports System.Configuration '添加对配置文件的引用,配置文件命名空间 Imports System.Reflection '添加对反射的引用 Public Class DataAccess '通过配置文件获取D层程序集的名称和命名空间的名称(一般情况下相同):DAL Dim AssemblyName As String = System.Configuration.ConfigurationManager.AppSettings("assName") '数据库类型为:Sqlserver Dim db As String = System.Configuration.ConfigurationManager.AppSettings("DB") '创建D层类SqlUserInfoDAL的实例 Public Function CreateUserInfo() As IDAL.IUserInfo Dim dalUserInfoName As String = AssemblyName & "." & db & "UserInfoDAL" '声明要实例化的D层类的名称 Return CType(Assembly.Load(AssemblyName).CreateInstance(dalUserInfoName), IUserInfo) End Function End Class</span>
当时只是知道这么写,如果更改数据库类型,直接更改value值,其他都不用改变。通过这次ITOO中IOC的使用对反射又有了一个系统的认识。
反射,可以在加载程序运行时,动态获取和加载并获取到程序集的信息,但没加反射之前都是在编译时获取和加载并获取程序集的信息,所以它的好处也就是在程序运行状态动态替换程序集。这次才知道ITOO中IOC容器是通过反射实现的,自己动手把他们的demo敲了一遍,看到了如何通过读取dll的生成路径加载并遍历dll中的类、方法、属性及属性特性等。
一、反射基本使用
这里例子中有一个User类,User类的生成路径改成ReflectionTest的bin/Debug目录下,在ReflectionTest没有添加对User任何引用的情况下,实现对User中属性和方法的调用。
解决方法目录:
User类:
namespace DAL { public class User { //字段 public string Field = "Hello World"; //属性 public string Name { get;set; } //无参构造函数 public User() { this.Name = "无参构造函数"; } //有参构造函数 public User(string name) { this.Name = name; } //public方法 public void publicMethod() { Console.WriteLine(string.Format ("调用一个公有方法")); } //private方法 public void privateMethod() { Console.WriteLine(string.Format("调用一个私有方法")); } //static 方法 public static string staticMethod() { return "调用一个静态方法"; } //public带参带返回值方法 public string PublicMethod(string name) { return string.Format ("调用一个带参带返回值公有方法"); } } }
1、加载程序集
//获取程序集 Assembly assembly = Assembly.Load("DAL");
2、加载类
方法一:先获取对象类型,通过Activator创建实例
//获取程序集对象类型 Type type = assembly.GetType("DAL.User"); #region 和下面先反射构造函数效果一致 //使用Activator创建实例(无参构造函数) var UserNoPara = Activator.CreateInstance(type); //使用Activator创建实例(有参构造函数) var UserHasPara = Activator.CreateInstance(type, "liliping"); #endregion
方法二:使用构造函数创建类(先反射创建构造函数,再使用构造函数创建类)
//使用有参构造函数创建类(先反射创建构造函数,再使用构造函数创建类) ConstructorInfo NoPara = type.GetConstructor(new Type[] { }); var UserNoPara = NoPara.Invoke(new object[] { }); //使用有参构造函数创建类(先反射创建构造函数,再使用构造函数创建类) ConstructorInfo HasPara = type.GetConstructor(new Type[] { typeof(string) }); var UserHasPara = HasPara.Invoke(new object[] { "liliping" });
3、加载方法
方法一:通过InvokeMember
//反射public方法(无参) object returnpublic = type.InvokeMember("publicMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, UserNoPara, null); Console.WriteLine(returnpublic); //反射public方法(有参) string returnMethod = type.InvokeMember("PublicMethod",BindingFlags.InvokeMethod |BindingFlags .OptionalParamBinding ,null,UserHasPara ,new object []{"liliping"})as string ; Console.WriteLine (returnMethod); //反射private方法 object returnprivate = type.InvokeMember("privateMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance , null, UserNoPara, null); Console.WriteLine(returnprivate); //反射static方法 object returnStatic=type.InvokeMember("staticMethod",BindingFlags.InvokeMethod |BindingFlags .Public |BindingFlags .Static ,null ,null,new object []{} ) as string ; Console.WriteLine(returnStatic );
方法二:通过MethodInfo方法加载类的方法
//反射public方法(无参) MethodInfo method = type.GetMethod("publicMethod"); object methodinfo = method.Invoke(UserNoPara, null); Console.WriteLine(methodinfo);
4、反射和设置属性
//反射属性 var name = type.InvokeMember("Name",BindingFlags.GetProperty |BindingFlags.Public |BindingFlags .Instance ,null,UserNoPara ,new object[]{} ) as string ; Console.WriteLine (name ); //设置属性 type.InvokeMember("Name",BindingFlags.SetProperty |BindingFlags .Public |BindingFlags .Instance ,null,UserNoPara ,new object []{"NewName"}); //反射字段 string field = type.InvokeMember("Field",BindingFlags.GetField |BindingFlags.Public |BindingFlags .Instance ,null,UserNoPara ,new object []{}) as string ; //设置字段 type.InvokeMember("Field", BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance, null, UserNoPara, new object[] { "NewFiled" });
二、ITOO中使用
从3.0框架中B、D中工厂都去除,IOC容器代之,配置文件中将需要的类key—value配好,程序加载时都给实例化好,放在一个大的Hashtable中,用的时候根据key拿到自己需要的类。
配置文件:
<!--容器的相关配置--> <configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" /> <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> </sectionGroup> </configSections>
<!--B层的的注解--> <object id="RateBll" type="ITOO.ResultSystemSet.BLL.RateBll,ITOO.ResultSystemSet.BLL" singleton="false" /> <object id="DictionaryBll" type="ITOO.ResultSystemSet.BLL.DictionaryBll,ITOO.ResultSystemSet.BLL" singleton="false" /> <object id="DictionaryTypeBll" type="ITOO.ResultSystemSet.BLL.DictionaryTypeBll,ITOO.ResultSystemSet.BLL" singleton="false" /> <!--B层的的注解-->
WCF调用拿到B层接口:
这里写在配置文件中的id值,然后使用时会根据ID在容器中找到对应的value。
这是对反射的理解,一步步积累。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u010097777/article/details/47131065