反射再认识

来源:互联网 发布:新疆的网络管制 编辑:程序博客网 时间:2024/05/22 04:44

         最开始接触反射是在机房收费系统中,是通过抽象工厂+反射防止更换数据库,在配置文件中定义好keyvalue,程序执行时根据key找到对应的value值,

配置文件代码:

<span style="font-size:18px;">      <appSettings>             <add key ="assName" value ="DAL"/>            <add key ="DB" value ="Sqlserver"/>        </appSettings></span>  

工厂层也通过配置文件中keyvalue拿到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值,其他都不用改变。通过这次ITOOIOC的使用对反射又有了一个系统的认识。

        反射,可以在加载程序运行时,动态获取和加载并获取到程序集的信息,但没加反射之前都是在编译时获取和加载并获取程序集的信息,所以它的好处也就是在程序运行状态动态替换程序集。这次才知道ITOOIOC容器是通过反射实现的,自己动手把他们的demo敲了一遍,看到了如何通过读取dll的生成路径加载并遍历dll中的类、方法、属性及属性特性等。

一、反射基本使用

        这里例子中有一个User类,User类的生成路径改成ReflectionTestbin/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框架中BD中工厂都去除,IOC容器代之,配置文件中将需要的类keyvalue配好,程序加载时都给实例化好,放在一个大的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。

这是对反射的理解,一步步积累。

参考文章:Relect中MethodInfo使用方法

          Type.InvokeMember方法


0 0
原创粉丝点击