程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#提高知識-001:反射的應用和原理(一)

C#提高知識-001:反射的應用和原理(一)

編輯:C#入門知識

在項目中,程序集間的相互引用是經常遇到的。比如,主程序引用各分模塊,各分模塊引用公用程序集,以及平行的程序集間為了某些功能的實現也需要相互引用。這樣的引用一方面是迫不得已的選擇,而另一方面也反映出系統設計的水平。下面,簡單介紹一下C#中的一種機制——反射。反射可以在避免某些情況下的程序集引用問題,比如主程序引用各功能模塊的問題,當然其它模塊間也是可以用反射的,只是使用是否方便這些問題需要在使用前根據實際情況進行考慮。本文以主程序加載分模塊為例,介紹一下反射的使用。 所謂反射,就是對程序集或模塊利用基礎類型進行解析,然後還原出一個對象模型,在調用者工作域裡運行的一個過程。其核心部分就是解析。工作原理是這樣的。 無論你創建的多麼結構復雜的類,歸根結底都是由元數據構成的。如下, [csharp]  public class Person    {        private string name;              private int  age;              private string content;    }       在程序編譯時,編譯器會創建類型表,字段表,方法表或其它表。再利用System.Reflection命名空間中的包含的類型進行解析,也可以看成對比的過程,將要被反射的程序集中的表讀出,根據System.Reflection的基本類型,進行重組,從而還原出原來程序集的結構。 例如,序列化的過程就是使用了反射,序列化格式器將被序列化的對象中的字段的值獲取出來,然後寫入一個字節流,進行傳輸;因為字節流傳輸不容易出錯或信息丟失。接收到字節流後,根據基本類型再還原出原對象的模型。 反射中,System.Type類型很重要,它遍歷被反射的表中的類型和反射中的基本類型進行比較,然後判斷出當前是什麼類型。 簡單了解了原理,那麼再看如何使用的。 建一個工程,包含主程序和子程序集,如圖   主程序生成在SetupApp文件夾中,子程序生成在\SetupApp\Library\中。 子程序的程序入口需要遵循一些約定,比如入口類名字需要都一樣,這樣才可統一加載。 [csharp]   namespace ReflecLibrary2   {       public class MainWindow       {           public MainWindow()           {               Welcome();           }                 private void Welcome()           {               Console.Write(@"當前程序為:ReflecLibrary2 ");                     Console.WriteLine(@"開始執行ReflecLibrary2!");           }       }   }         namespace ReflectLibrary1   {       public class MainWindow       {           public MainWindow()           {               Welcome();           }                 private void Welcome()           {               Console.Write(@"當前程序為:ReflectLibrary1 ");                     Console.WriteLine(@"開始執行ReflecLibrary1!");           }       }   }     然後看調用的部分, [csharp]   class Program       {           static void Main(string[] args)           {               /////////////////////設置約定的規則,比如需要加載的程序的目錄,程序集程序入口的類///////////////////               string startPath = AppDomain.CurrentDomain.BaseDirectory + @"Library\";                     string suffix=@".dll";                     string commonMainClass = @"MainWindow";                     DirectoryInfo directory = new DirectoryInfo(startPath);                     /////////////////////將程序集文件名讀入,這裡其實只需要string類型的路徑即可,               //////為了後面處理字符串方便所以才讀取文件信息               var libraries = directory.GetFiles().OrderBy(o=>o.FullName);                     List<FileInfo> loadDlls = new List<FileInfo>();                     if (libraries != null)               {                   foreach (FileInfo item in libraries)                   {                       if (item.FullName.ToLower().EndsWith(suffix))                       {                           loadDlls.Add(item);                       }                   }               }                     /////////////////////執行程序集///////////////////               //程序集1               Assembly assembly1 = Assembly.LoadFile(loadDlls[0].FullName.Replace(@"/", @"\"));                     string typeName1 = loadDlls[0].Name.Replace(loadDlls[0].Extension,string.Empty) + @"." + commonMainClass;                     assembly1.CreateInstance(typeName1);                     //程序集2               Assembly assembly2 = Assembly.LoadFile(loadDlls[1].FullName.Replace(@"/", @"\"));                     string typeName2 = loadDlls[1].Name.Replace(loadDlls[0].Extension, string.Empty) + @"." + commonMainClass;                     assembly2.CreateInstance(typeName2);                     Console.ReadLine();           }     各個部分的作用都寫在了注釋中。 運行結果就是,程序集1和程序集2中的方法都執行了。當然這裡只是為了方便說明只寫了一個方法,實際上 public MainWindow()         {             Welcome();         } 就是子程序的入口。 結果如下, 那麼反射我們就有了一個直觀的理解,裡面的詳細原理,下一篇繼續介紹。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved