熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

C#反射淺析

2013-11-13 10:00:13  來源: .NET編程 
首先了解C#反射的概念反射是一個運行庫類型發現的過程通過反射可以得到一個給定程序集所包含的所有類型的列表
   
    這個列表包括給定類型中定義的方法字段屬性和事件也可以動態的發現一組給定類支持的借口方法的參數和其他
   
    相關信息如基類命名空間數據清單等
   
    C#反射命名空間詳細介紹
   
    SystemReflection命名空間內的各類型
   
    () Assembly通過它可以加載了解和操縱一個程序集
   
    () AssemblyName 通過它可以找到大量隱藏在程序集的身份中的信息如版本信息區域信息等
   
    () EventInfo 事件的信息
   
    () FieldInfo 字段的信息
   
    () MethodInfo 方法的信息
   
    () ParameterInfo 參數的信息
   
    () PropertyInfo 屬性的信息
   
    () MemberInfo 是抽象基類為 EventInfoFieldInfo MethodInfoPropertyInfo等類型定義了公共的行為
   
    () Module 用來訪問帶有多文件程序集的給定模塊
   
    SystemType類
   
    SystemType支持的成員可以分為這樣幾類
   
    () Is*** 用來檢查一個類型的元數據如IsAbstractIsClassIsValueType等等
   
    () Get*** 用來從類型得到指定項目如GetEvent()得到類型的一個指定的事件(EventInfo)
   
    另外這些方法都有一個單數版本和一個復數版本如GetEvent()對應有一個復數版本GetEvents()
   
    該方法返回一個相關的EventInfo數組
   
    () FindMembers() 根據查詢條件返回一個MemberInfo類型的數組
   
    ()GetType() 該靜態方法根據一個字符串名稱返回一個Type實例
   
    ()InvokeMember() 對給定項目進行晚期綁定
   
    得到一個Type類型實例的三種方法
   
    因為Type是一個抽象類所以不能直接使用new關鍵字創建一個Type對象
   
    ()使用SystemObjectGetType()
   
    Person pe=new Person() //定義pe為person類的一個對象
   
    Type t=peGetType()
   
    ()使用SystemTypeGetType()靜態方法參數為類型的完全限定名
   
    Type t=TypeGetType(EntityPerson 該方法被重載允許指定兩個布爾類型的參數一個用來控制當前類型不能找到時是否拋出異常
   
    另一個用來指示是否區分字符串大小寫
   
    Type t=TypeGetType(EntityPersonfalsetrue) 注意到傳入的字符串並沒有包含類型所在的程序集信息此時該類型便被認為是定義在當前執行的程序集中的
   
    要得到一個外部私有程序集的類型元數據時字符串參數必須使用類型完全限定名加上類型所在程序集的友好名字
   
    Type t=TypeGetType(EntityPersonEntity //Entity即為類型所在程序集的友好名字 嵌套類型傳入的字符串可以指定一個+標記來表示一個嵌套類型
   
    如希望得到一個嵌套在person類中的枚舉類型City的類型信息則可以這樣
   
    Type t=TypeGetType(Entityperson+City
   
    ()使用typeof運算符
   
    Type t=typeof(person) 三種方法的比較
   
    使用第一種方法必須先建立一個實例而後兩種方法不必先建立實例但使用typeof運算符仍然需要知道類型的編譯時信息
   
    而使用SystemTypeGetType()靜態方法不需要知道類型的編譯時信息所以是首選方法
   
    一個最簡單的C#反射實例首先編寫類庫如下
   
    namespace ReflectionTest
   
    {
   
    public class WriteTest
   
    {
   
    //帶參數的公共方法
   
    public void WriteString(string s int i)
   
    {
   
    ConsoleWriteLine(WriteString: + s + iToString())
   
    }
   
    //帶一個參數的靜態方法
   
    public static void StaticWriteString(string s)
   
    {
   
    ConsoleWriteLine(StaticWriteString: + s)
   
    }


   
    //不帶參數的靜態方法
   
    public static void NoneParaWriteString()
   
    {
   
    ConsoleWriteLine(NoParaWriteString
   
    }
   
    }
   
    }
   
    class TestApp
   
    {
   
    public static void Main()
   
    {
   
    Assembly ass;
   
    Type type;
   
    Object obj;
   
    //用來測試靜態方法
   
    Object any = new Object()
   
    //指定類庫文件必須使用絕對路徑不能使用相對路徑
   
    ass = AssemblyLoadFile(@D:\Source Code\C#Sudy\Reflection\\ReflectTestdll
   
    //命名空間和類的名字必須一起指定
   
    type = assGetType(ReflectionTestWriteTest
   
    /**//*example*/
   
    MethodInfo method = typeGetMethod(WriteString
   
    string test = test;
   
    int i = ;
   
    Object[] parametors = new Object[]{testi};
   
    //在例子種必須實例化反射要反射的類因為要使用的方法並不是靜態方法
   
    //創建對象實例
   
    obj = assCreateInstance(ReflectionTestWriteTest
   
    //執行帶參數的公共方法
   
    methodInvoke(obj parametors)
   
    //methodInvoke(any parametors)//異常必須實例化反射要反射的類因為要使用的方法並不是靜態方法
   
    /**//*example*/
   
    method = typeGetMethod(StaticWriteString
   
    methodInvoke(null new string[] { test}) //第一個參數忽略
   
    //對於第一個參數是無視的也就是我們寫什麼都不會被調用
   
    //即使我們隨便new了一個any這樣的Object當然這種寫法是不推薦的
   
    //但是對應在例子種我們如果Invoke的時候用了類型不一致的實例來做為參數的話將會導致一個運行時的錯誤
   
    methodInvoke(obj new string[] { test})
   
    methodInvoke(any new string[] { test})
   
    /**//*example*/
   
    method = typeGetMethod(NoneParaWriteString //調用無參數靜態方法的例子這時候兩個參數我們都不需要指定用null就可以了s
   
    methodInvoke(null null)
   
    }
   
    }
   
    從上面的總結中可以看出對於外部調用的動態庫應用反射時要用到AssemblyLoadFile()然後才是獲取類型執行方法等
   
    當用反射創建當前程序集中對象實例或執行某個類下靜態方法時只需通過TypeGetType(類的完整名


From:http://tw.wingwit.com/Article/program/net/201311/12264.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.