C#反射機制詳解


反射的定義:審查元數據並收集關於它的類型信息的能力,元數據(編輯后的基本數據單元)就是一大堆表,編譯器會創建一個類定義表,一個字段定義表,一個方法定義表等,System.Reflection命名空間包含的幾個類,允許你反射(解析)這些元數據的代碼

一、反射的作用:
動態的創建類型的實例,將類型邦定到現有對象,或從現有對象中獲取類型 
應用程序需要在運行時從某個特定的程序集中載入一個特定的類型,以便實現某個任務時可以用到反射 
反射主要應用於類庫,這些類庫需要知道一個類型的定義,以便提供更多的功能

二、應用要點:
現實應用程序中很少使用到反射 
使用反射動態邦定需要犧牲性能 
有些元數據信息是不能通過反射獲取的 
某些反射類型是專門為那些CLR開發編輯器開發使用的,所以你要意思到不是所有反射類型都是可以使用的

三、取得Assembly的方法:
Assembly.Load 
Assembly.LoadFile 
Assembly.LoadFrom 
Type對象的Assembly方法

四、反射的成員:
MemberInfo-成員 
ConstructorInfo-結構 
FieldInfo-字段 
MethodInfo-方法 
PropertyInfo-屬性 
EventInfo-事件

五、根據反射取得對象的Member信息
private  void WriteReflectionInfo()
{
Type testType =  typeof(Test);
Assembly assembly = testType.Assembly;
Response.Write( " Assembly: " + assembly.FullName +  " <br/> ");
Type[] typeList = assembly.GetTypes();    //  獲取類型
//  針對每個類型獲取詳細信息
foreach (Type type  in typeList)
{
    Response.Write( " ------------------------ " + type.Namespace + type.Name +  " ------------------------<br/> ");
     //  獲得類型的結構信息
    ConstructorInfo[] constructs = type.GetConstructors();

     //  獲得類型的字段信息
    FieldInfo[] fields = type.GetFields();
    Response.Write( " <b>類的公共字段信息如下:</b> " +  " <br/> ");
     int a1 =  1;
     foreach (FieldInfo field  in fields)
    {
        Response.Write((a1++).ToString() +  " " + field.Name +  " <br/> ");
    }

     //  獲得方法信息
    MethodInfo[] methods = type.GetMethods();

    Response.Write( " <b>類的公共方法如下:</b> " +  " <br/> ");
     int a2 =  1;
     foreach (MethodInfo method  in methods)
    {
        ParameterInfo[] parameters = method.GetParameters();
        ParameterInfo reparam = method.ReturnParameter;
        Response.Write((a2++).ToString() +  " " + reparam.ParameterType.Name +  "   " + method.Name +  " ( ");
         int index =  0;
         foreach (ParameterInfo para  in parameters)
        {
             if (index++ < parameters.Length -  1)
                Response.Write(para.ParameterType.Name +  "   " + para.Name +  " , ");
             else
                Response.Write(para.ParameterType.Name +  "   " + para.Name);
        }
        Response.Write( " )<br/> ");
    }

     //  獲得屬性的信息
    PropertyInfo[] propertys = type.GetProperties();

    Response.Write( " <b>類的公共屬性如下:</b> " +  " <br/> ");
     int a3 =  1;
     foreach (PropertyInfo pro  in propertys)
    {
        Response.Write((a3++).ToString() +  " " + pro.PropertyType.Name +  "   " + pro.Name +  " { ");
         if (pro.CanRead) Response.Write( " get; ");
         if (pro.CanWrite) Response.Write( " set; ");
        Response.Write( " }<br/> ");
    }
     //  獲得事件信息
    EventInfo[] events = type.GetEvents();

    Response.Write( " <b>類的成員如下:</b> " +  " <br/> ");
     //  獲得成員
     int a4 =  1;
     foreach (MemberInfo mi  in type.GetMembers())
    {
        Response.Write((a4++).ToString() +  " " + mi.MemberType.ToString() +  "  :  " + mi.Name +  " <br/> ");
    }
}

六、動態創建對象
Assembly對象的 CreateInstance方法 
Activator. CreateInstance方法 
Type對象的 InvokeMember方法
//  使用Assembly的CreateInstance方法來取得對象的實例
private  void Assembly_CreateInstance()
{
     string assemblyName =  " SqlModel ";
     string className = assemblyName +  " .Member ";
     //  創建無參數實例
    IDAL.IMember member = (IDAL.IMember)Assembly.Load(assemblyName).CreateInstance(className);
    Response.Write( " 創建無參數實例: " + member.ID +  " <br/> ");
     //  創建有參數實例
    Object[] parameters =  new Object[ 1];
    parameters[ 0] =  10000;
    IDAL.IMember member1 = (IDAL.IMember)Assembly.Load(assemblyName).CreateInstance(className,  false, BindingFlags.Default,  null, parameters,  nullnull);
    Response.Write( " 創建有參數實例: " + member1.ID +  " <br/> ");
}

//  使用Activator的CreateInstance方法來取得對象的實例
private  void Activator_CreateInstance()
{
     string assemblyName =  " SqlModel ";
     string className = assemblyName +  " .Member ";
     //  創建無參數實例
    System.Runtime.Remoting.ObjectHandle obj = Activator.CreateInstance(assemblyName, className);
    IDAL.IMember member = (IDAL.IMember)obj.Unwrap();
    Response.Write( " 創建無參數實例: " + member.ID +  " <br/> ");
     //  創建有參數實例
    Object[] parameters =  new Object[ 1];
    parameters[ 0] =  10000;
    System.Runtime.Remoting.ObjectHandle obj1 = Activator.CreateInstance(assemblyName, className,  false, BindingFlags.CreateInstance,  null, parameters,  nullnullnull);
    IDAL.IMember member1 = (IDAL.IMember)obj1.Unwrap();
    Response.Write( " 創建有參數實例: " + member1.ID +  " <br/> ");
}

//  使用Type的InvokeMember方法來取得對象的實例
private  void Type_InvokeMember()
{
     string assemblyName =  " SqlModel ";
     string className = assemblyName +  " .Member ";
    Assembly assem = Assembly.Load(assemblyName);
    Type type = assem.GetType(className);    //  註意這里如果使用Type.GetType來取得Type的話,那麼assemblyName指定的類一定要是強命名的
    
//  創建無參數實例
    IDAL.IMember member = (IDAL.IMember)type.InvokeMember(className, BindingFlags.CreateInstance,  nullnullnull);
    Response.Write( " 創建無參數實例: " + member.ID +  " <br/> ");
     //  創建有參數實例
    Object[] parameters =  new Object[ 1];
    parameters[ 0] =  10000;
    IDAL.IMember member1 = (IDAL.IMember)type.InvokeMember(className, BindingFlags.CreateInstance,  nullnull, parameters);
    Response.Write( " 創建有參數實例: " + member1.ID +  " <br/> ");
}

七、動態調用對象方法

Type對象的 InvokeMember方法 
MethodInfo對象的Invoke方法
//  Type對象的 InvokeMember方法來動態調用方法
private  void InvokeMember()
{
     string assemblyName =  " SqlModel ";
     string className = assemblyName +  " .Member ";
     string methodName = String.Empty;
     string result = String.Empty;
    Assembly assem = Assembly.Load(assemblyName);
    Object obj = assem.CreateInstance(className);
    Type type = assem.GetType(className);    //  註意這里如果使用Type.GetType來取得Type的話,那麼assemblyName指定的類一定要是強命名的
    
//  動態調用無參數的方法
    methodName =  " GetName ";
    result = ( string)type.InvokeMember(methodName, BindingFlags.InvokeMethod,  null, obj,  null);
    Response.Write(methodName +  " 方法的返回值: " + result +  " <br/> ");
     //  動態調用有參數的方法
    methodName =  " Update ";
    Object[] methodParams =  new Object[ 1];
    methodParams[ 0] = DateTime.Now;
    result = ( string)type.InvokeMember(methodName, BindingFlags.InvokeMethod,  null, obj, methodParams);
    Response.Write(methodName +  " 方法的返回值: " + result +  " <br/> ");
     //  動態調用參數構架函數的帶有參數的方法
    Object[] parameters =  new Object[ 1];
    parameters[ 0] =  10000;
    obj = assem.CreateInstance(className, false,BindingFlags.CreateInstance,  null, parameters,  nullnull);
    result = ( string)type.InvokeMember(methodName, BindingFlags.InvokeMethod,  null, obj, methodParams);
    Response.Write(methodName +  " 方法的返回值: " + result +  " <br/> ");
}

//  MethodInfo對象的Invoke方法來動態調用方法

private  void MethodInfo_Invoke()
{
     string assemblyName =  " SqlModel ";
     string className = assemblyName +  " .Member ";
     string methodName = String.Empty;
     string result = String.Empty;

    Assembly assem = Assembly.Load(assemblyName);
    Object obj = assem.CreateInstance(className);
    Type type = assem.GetType(className);    //  註意這里如果使用Type.GetType來取得Type的話,那麼assemblyName指定的類一定要是強命名的
    
//  動態調用無參數的方法
    methodName =  " GetName ";
    MethodInfo methodInfo = type.GetMethod(methodName);
    result = ( string)methodInfo.Invoke(obj,  null);
    Response.Write(methodName +  " 方法的返回值: " + result +  " <br/> ");
     //  動態調用有參數的方法
    methodName =  " Update ";
    Object[] methodParams =  new Object[ 1];
    methodParams[ 0] = DateTime.Now;
    MethodInfo method = type.GetMethod(methodName);
    result = ( string)method.Invoke(obj, methodParams);
    Response.Write(methodName +  " 方法的返回值: " + result +  " <br/> ");
}

--------------------------------------------------------------------------------
以上所使用的SqlModel.Member為:
新建一個SqlModel類庫,在其下建立一個Member的類

namespace SqlModel
{
     public  class Member : IDAL.IMember
    {
         private  int _id =  100;
         public  int ID
        {
             get {  return _id; }
             set { _id = value; }
        }
         private  string _name =  " limin ";
         public  string Name
        {
             get {  return _name; }
             set { _name = value; }
        }

         public Member() { }
         public Member( int id)
        {
            _id = id;
        }

         private  void Init()
        { }

         public  string GetName()
        {
             return _name;
        }
         public  string Update (DateTime cdate)
        {
             return  " { " + String.Format( " ID:{0},Name:{1},CreateDate:{2} ",_id,_name,cdate) +  " } ";
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM