您的位置:首页 > 其它

反射再认识

2015-07-29 17:50 344 查看
最开始接触反射是在机房收费系统中,是通过抽象工厂+反射防止更换数据库,在配置文件中定义好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。
这是对反射的理解,一步步积累。
参考文章:Relect中MethodInfo使用方法
Type.InvokeMember方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: