System.Reflection.Assembly類是一個比較常用到的類,在反射中就經常用到。
由於這個類實在有太多的字段、屬性與方法。實在不想將一個個屬性方法從MSDN復制出來然后逐個屬性、方法敲一次,我想改變一下學習方法,從實際運用學習。
一、加載程序集並執行方法
使用反射加載程序集並執行方法,加載程序集主要使用LoadFrom()方法。
static void Main(string[] args) { Assembly ass = Assembly.LoadFrom(@"D:\test.dll"); Type type = ass.GetType("Test.Add"); //注意要輸入全部路徑,包括命名空間 object obj = Activator.CreateInstance(type); MethodInfo Add = type.GetMethod("AddCalculate"); //根據方法名獲取MethodInfo對象 int i = (int)Add.Invoke(obj, new object[2] { 1, 2 }); Console.WriteLine(i); Console.ReadKey(); }
以上程序運行輸出3。
注意在Assembly里面的加載程序集有3個方法,分別是Load、LoadFrom和LoadFile。這3個方法有什么異同呢?
- 如果你引用了命名空間,那么就直接Load()方法,參數里面寫上命名空間+類名就可以加載了。
- 如果僅僅知道一個dll文件的那么就要用LoadFrom()方法了,參數里面直接填寫完整的路徑。
LoadFrom 方法具有以下缺點。請考慮改用 Load。
- 如果已加載一個具有相同標識的程序集,則即使指定了不同的路徑,LoadFrom 仍返回已加載的程序集。
- 如果用 LoadFrom 加載一個程序集,隨后加載上下文中的一個程序集嘗試加載具有相同顯示名稱的程序集,則加載嘗試將失敗。對程序集進行反序列化時,可能發生這種情況。
總結: LoadFrom只能用於加載不同標識的程序集, 也就是唯一的程序集, 不能用於加載標識相同但路徑不同的程序集。
3.LoadFile 加載指定路徑上的程序集文件的內容。
這個方法是從指定的文件來加載程序集,它是調用外部的API實現的加載方式,和上面Load,LoadFrom方法的不同之處是這個方法不會加載此程序集引用的其他程序集,也就是不會加載程序的依賴項。而同時也是不能加載相同標識的程序集的。
4.GetExecutingAssembly獲取當前正在執行的程序集。
示例:
static void Main(string[] args) { //需引用命名空間 Assembly assm = Assembly.Load("fanshe"); Console.WriteLine(assm.FullName); //輸出 fanshe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null //依靠路徑 Assembly assm1 = Assembly.LoadFrom(@"D:\fanshe.dll"); Console.WriteLine(assm1.FullName); ////輸出 fanshe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null //與Assembly.LoadFrom基本一樣,只是如果被加載的dll,還依賴其他的dll的話,被依賴的對象不會加載 Assembly assm2 = Assembly.LoadFile(@"D:\fanshe.dll"); Console.WriteLine(assm2.FullName); //當前正在執行的程序集 Assembly assm3 = Assembly.GetExecutingAssembly(); Console.WriteLine(assm3.FullName); Console.ReadKey(); }
二、讀取程序集中嵌入的資源
讀取嵌入的資源,主要有如下兩個方法:
- GetManifestResourceNames:讀取嵌入的資源名稱。
- GetManifestResourceStream:讀取嵌入的資源為流。
static void Main(string[] args) { Assembly ass = Assembly.LoadFrom(@"D:\test.dll"); string[] names = ass.GetManifestResourceNames(); foreach (string name in names) { Console.WriteLine("所有的嵌入資源名:" + name); } Stream myStream = ass.GetManifestResourceStream("Test.1.txt"); Console.WriteLine(); using (StreamReader sr = new StreamReader(myStream, Encoding.Default)) { //嵌入的資源1.txt的內容 Console.WriteLine("嵌入的資源1.txt的內容:" + sr.ReadToEnd()); } Console.ReadKey(); }