反射(Reflection): 就是能夠在運行時刻查詢到類型資訊的進程。他有以下的各個部分,可以根據你應用的需要選擇其中的一個或者某些來使用:1.
Assembly:使用它來定義和載入一些Assembly, 載入存在於Assembly 中的modules,並且可以得到這個Assembly的類型,同時建立他的執行個體(MSN原文:Use Assembly to define and load assemblies, load modules that are listed in the assembly manifest, and locate a type from this assembly and create an instance of it.) 2.
Module: 可以使用它來尋找到包含該module的Assembly資訊,並且可以得到該module中的各種類;同時你不單單可以得到所有的全域函數和其他變數,也可以得到定義在該module中的非全域方法(MSN原文:Use Module to discover information such as the assembly that contains the module and the classes in the module. You can also get all global methods or other specific, nonglobal methods defined on the module.) 3.
ConstructorInfo: 使用它你可以尋找到一個建構函式的名字,參數,存取權限和實現的細節(比如說它是抽象的,還是虛擬);使用某個類型的GetConstructors 和 GetContructor方法來運行他的建構函式(MSN原文:Use ConstructorInfo to discover information such as the name, parameters, access modifiers (such as
public or
private), and implementation details (such as
abstract or
virtual) of a constructor. Use the GetConstructors or GetConstructor method of a Type to invoke a specific constructor.) 4.
MethodInfo: 通過他您可以尋找到某個方法的名字,傳回型別,參數,存取權限和實現的細節(比如說它是抽象的,還是虛擬?);它也提供兩個方法來運行制定的方法,他們分別是:GetMethods和GetMethod.Use (MSN原文:MethodInfo to discover information such as the name, return type, parameters, access modifiers (such as
public or
private), and implementation details (such as
abstract or
virtual) of a method. Use the GetMethods or GetMethod method of a Type to invoke a specific method.) 5.
FieldInfo: 使用它你可以尋找到某個欄位的名字,傳回型別,參數,存取權限和實現的細節(比如說是否是靜態?);它提供了get 和 set方法來訪問欄位。(MSN原文:Use FieldInfo to discover information such as the name, access modifiers (such as
public or
private) and implementation details (such as
static) of a field, and to get or set field values.) 6. EventInfo:使用它你將可以尋找到某一個事件的名字,事件控制代碼的資料類型,自訂的屬性,聲明的類型和相關的類型等等的資訊,當然你可以增加或者去除一個事件。(MSN原文:Use EventInfo to discover information such as the name, event-handler data type, custom attributes, declaring type, and reflected type of an event, and to add or remove event handlers.) 7. PropertyInfo: 使用它你可以尋找到某個屬性的名字, 資料類型, 聲明的類型,關聯的類型 和唯讀或者可寫狀態等一些資訊; 當然你可以得到和設定他的值。(MSN原文:Use PropertyInfo to discover information such as the name, data type, declaring type, reflected type, and read-only or writable status of a property, and to get or set property values.) 8. MSN原文:Use ParameterInfo to discover information such as a parameter's name, data type, whether a parameter is an input or output parameter, and the position of the parameter in a method signature. 9. MSN原文:Use CustomAttributeData to discover information about custom attributes when you are working in the reflection-only context of an application domain.
CustomAttributeData allows you to examine attributes without creating instances of them.看了上面的那麼多字,你可以能還不知道怎麼應用,不過沒關係,下面將會提供一些例子,在看例子之前,我們先看看Type類。
System.Type它是整個放射的中心,上面的各個部分都是圍繞著他來進行的。他能夠查詢類型名字,類型中包含的模組和名稱空間,以及判斷該類型是實值型別還是參考型別。1. 得到類型名字:float f = 1.0f;Type t = f.GetType();Console.WriteLine(t.Name);//這樣就可以得到他的類型名字了。2. 通過一個類型名字得到一個Type:Type t = Type.GetType(“System.Int32”);Console.WriteLine(t.Name);3. 下面把查詢類型的一部分列出來:Type t = Type.GetType(typeName);t.IsAbstract;t.IsAnsiClass;t.IsArray;t.IsEnum;t.IsClass……
Assembly的應用在這裡就介紹一個稱為“外掛程式”技術的例子作為對這部分的總結吧!現在使用一個現實中的例子,我在上海的某某地段開了一個超級市場,裡面有各種各種牌子的店鋪,你可以在超級市場新開設店鋪,當然有一些店鋪因為生意不好,不得不退出超級市場。那麼在程式裡面應該怎麼樣來實現這個過程呢?因為店鋪的開張或倒閉不是固定的,是動態, 這樣我們就不能夠在主程式中固化這些店鋪,這個時候就需要我們動態載入這些店鋪了,下面請看如下實現:1. 開設超級市場:首先我們需要一個商鋪管理類,用它來管理開店和關閉店鋪,代碼如下: public class ShopManager { protected static ShopManager m_ShopManager; protected ShopManager() { } public static ShopManager GetShopManager() { if (m_ShopManager == null) { m_ShopManager = new ShopManager(); } return m_ShopManager; } public List<string> GetShops() { List<string> shops = new List<string>(); string pluginFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"); if (!System.IO.Directory.Exists(pluginFolder)) return shops; foreach(string pluginFile in System.IO.Directory.GetFiles(pluginFolder, "*.dll")) { try { Assembly assembly = Assembly.LoadFile(pluginFile); foreach(Type type in assembly.GetTypes()) { if(!type.IsClass || type.IsNotPublic) continue; Type[] tempInterfaces = type.GetInterfaces(); if(((IList)tempInterfaces).Contains(typeof(IShop))) { IShop shop = (IShop)CreateInstance(type); shops.Add(shop.GetShopName()); } } } catch { } } return shops; } protected object CreateInstance(Type type, object[] args) { try { return Activator.CreateInstance(type, args); } catch (TargetInvocationException e) { throw e.InnerException; } } protected object CreateInstance(Type type) { return CreateInstance(type, null); } }接著定義個抽象的商鋪類,我們的管理類只知道這個類,代碼如下: public interface IShop { string GetShopName();}最後定義我們的超級市場類,請看代碼: public class Market { protected static Market m_Market; protected List<string> m_Shops = new List<string>(); protected Market() { //get all shops m_Shops = ShopManager.GetShopManager().GetShops(); } public void ShowShops() { foreach (string shop in m_Shops) { Console.WriteLine(shop); } } public static Market GetMarket() { if (m_Market == null) { m_Market = new Market(); } return m_Market; } }這樣整個市場就建立起來了。接著看看我們怎麼開設店鋪。2. 開設店鋪:首先建立一個店鋪的介面類,並提供一個函數叫著:string GetShopName();接著你就可以建立屬於你的店鋪了,這些具體的店鋪都必須繼承製店鋪的介面類,實現他的介面函數,至於你要自己要為你開設的店鋪建立什麼功能,是你自己的事情,超級市場是不會關心的。下面是兩個店鋪的例子:建立一個Class Library工程,命名為NikeShop,接下來是具體的代碼:using System;using System.Collections.Generic;using System.Text; using SuperMarket;namespace Shop{ public class NikeShop : IShop { public string GetShopName() { return "Nike"; } }}同樣再建立一個工程,叫做AdidasShop,代碼如下:using System;using System.Collections.Generic;using System.Text; using SuperMarket;namespace Shop{ public class AdidasShop : IShop { public string GetShopName() { return "Adidas"; } }}最後把你產生的店鋪的dll拷貝到plugin的檔案夾裡面就可以了。當你從新進入超級市場(啟動主程式)的時候就可以看到該店鋪了3. 關閉倒閉的店鋪:怎麼樣來關閉店鋪呢? 很簡單,我們只需要把這個店鋪對應的dll檔案從plugin裡面刪除就行,等你下次啟動並執行時候,你將看不到該店鋪了。基本上就這些了,有什麼問題,請留言,謝謝!