從程序集獲得類型
先說點題外話,現在技術真的發展太快了。我這邊還很多東西半生不熟
呢,那邊又出現了好多有趣的新東西讓你眼紅不已。學還是不學這還真是
個問題。Node.js 、bootstrap,我最近剛發現的新技術,其實他們已經
存在很久了,只是沒有接觸過而已。昨天晚上看Node.js一下子看到兩點
多,感覺真是太有意思了^,有興趣的可以去看看,大家多交流交流.
好了不廢話了,在前面的示例中,幾乎全部的MyClass信息都是通過反射得到的,但是有一個例外:
MyClass類型本身。雖然前面的示例可以動態確定MyClass的信息,但它們仍基于以下事實:事先知道
類型名MyClass,并且在typeof語句中使用它創建一個Type對象。盡管這種方式可能在很多環境中都有
用,但是要發揮反射的全部功能,就必須能通過分析其他程序集的內容動態的獲取可用的類型。
程序集提供了它包含的類和結構的信息。借助反射應用程序接口,可以加載程序集,獲取它的相
關信息并創建其公共可用類型的實例。通過使用這種機制,程序能夠搜素其環境,利用那些潛在的功能而
無需在編譯期間顯示的定義他們。由于類型的全部信息都可以被發現,因此不存在反射應用的內在限制。
為了獲取程序集的相關信息,首先需要創建一個Assembly對象。Assembly類并沒有定義公有的
構造函數,它的對象實例是通過類的一個方法獲得的。這里使用的LoadFrom()方法可以加載由文件名
指定的程序集,其形式如下:
static Assembly LoadFrom(string fileName)
一旦獲得了Assembly類型的對象,就可以通過調用該對象的GetType()來得到它所定義的類型
。基本形式如下:
Type[] GetTypes()
此方法返回一個數組,它包含了程序集的類型。
為了說明如何獲取程序集的類型,我們需要在解決方案中添加一個類庫,類庫名字為MyClasses,
在類庫中添加三個類:MyClass、AnotherClass、Demo。代碼如下:
程序集MyClasses代碼
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyClasses { public class MyClass { int x; int y; public MyClass(int i) { Console.WriteLine("一個參數的構造函數:"); x = y = i; } public MyClass(int i, int j) { Console.WriteLine("兩個參數構造函數:"); x = i; y = j; Show(); } public int Sum() { return x + y; } public bool IsBetween(int i) { if (x < i && i < y) return true; else return false; } public void Set(int a, int b) { Console.Write("函數:Set(int a, int b)"); x = a; y = b; Show(); } public void Set(double a, double b) { Console.Write("函數:Set(double a, double b)"); x = (int)a; y = (int)b; Show(); } public void Show() { Console.WriteLine("x:{0},y:{1}", x, y); } } public class AnotherClass { string msg; public AnotherClass(string msg) { this.msg = msg; } public void show() { Console.WriteLine(msg); } } public class Demo { public void test() { Console.WriteLine("我是打醬油的!!"); } } }
使用反射代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace Reflection { class Program { static void Main(string[] args) { ReflectAssemblyDemo(); Console.ReadKey(); } static void ReflectAssemblyDemo() { int val; Assembly asm = Assembly.LoadFrom("MyClasses.dll"); Type[] allTypes = asm.GetTypes(); foreach (Type type in allTypes) { Console.WriteLine("程序集中找到類:" + type.Name); } Console.WriteLine(); //使用第一個類 Type t = allTypes[0]; Console.WriteLine("使用類:" + t.Name); //獲得構造函數 ConstructorInfo[] ci = t.GetConstructors(); //顯示此類中的構造函數 Console.WriteLine("此類中的構造函數有:"); foreach (ConstructorInfo c in ci) { Console.Write(" " + t.Name + " ("); ParameterInfo[] pi = c.GetParameters(); for (int i = 0; i < pi.Length; i++) { Console.Write(pi[i].ParameterType.Name + " " + pi[i].Name); if (i + 1 < pi.Length) Console.Write(","); } Console.WriteLine(")"); } //獲取匹配的構造函數 int x; for (x = 0; x < ci.Length; x++) { ParameterInfo[] pi = ci[x].GetParameters(); if (pi.Length == 2) break; } if (ci.Length == x) { Console.WriteLine("沒有匹配的構造函數"); return; } else { object[] consargs = new object[2]; consargs[0] = 10; consargs[1] = 20; object reflectOb = ci[x].Invoke(consargs); Console.WriteLine("通過reflectOb調用方法"); Console.WriteLine(); MethodInfo[] mi = t.GetMethods(); foreach (MethodInfo m in mi) { //獲得方法參數 ParameterInfo[] pi = m.GetParameters(); if (m.Name.CompareTo("Set") == 0 && pi[0].ParameterType == typeof(int)) { object[] args = new object[2]; args[0] = 9; args[1] = 18; m.Invoke(reflectOb, args); } else if (m.Name.CompareTo("Set") == 0 && pi[0].ParameterType == typeof(double)) { object[] args = new object[2]; args[0] = 1.25; args[1] = 7.5; m.Invoke(reflectOb, args); } else if (m.Name.CompareTo("Sum") == 0) { val = (int)m.Invoke(reflectOb, null); Console.WriteLine("Sum is {0}", val); } else if (m.Name.CompareTo("IsBetween") == 0) { object[] args = new object[1]; args[0] = 13; if ((bool)m.Invoke(reflectOb, args)) { Console.WriteLine("13 is between x and y"); } } else if (m.Name.CompareTo("Show") == 0) { m.Invoke(reflectOb, null); } } } } } }
運行結果:
自此,反射部分基本內容寫完了.希望對大家有所幫助.現在正在進行WPF開發,我會把在項目開發中遇到的問題與解決方案及時與您分享,希望您能繼續關注.
最后,如果本文對您有所幫助,請點推薦,謝謝!
文章列表