動態載入dll,主要是為了擴充功能,增強靈活性而實現的。主要通過xml配置,來擷取所有要動態載入的dll,然後通過反射機制來調用dll中的類及其方法。
研究了一天,小有所得,寫了一個簡單的動態載入dll的通用模組,拿出來與大家分享一下:
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;namespace DynamicLoadDLL{ /// <summary> /// 動態載入dll /// </summary> public class LoadDLL { private Assembly ass = null; /// <summary> /// 載入dll /// </summary> /// <param name="dllPath">dll檔案路徑</param> public LoadDLL(string dllPath) { this.ass = Assembly.LoadFrom(dllPath); //利用dll的路徑載入(fullname) } /// <summary> /// 返回反射的dll /// </summary> /// <returns></returns> public Assembly GetAssembly() { return this.ass; } /// <summary> /// 擷取所有類名 /// </summary> /// <returns></returns> public Type[] GetClass() { return ass.GetTypes(); } /// <summary> /// 擷取程式集下的所有檔案名稱 /// </summary> /// <returns></returns> public Module[] GetModules() { return ass.GetModules(); } /// <summary> /// 擷取資訊清單檔案表中的檔案 /// </summary> /// <returns></returns> public FileStream[] GetFiles() { return ass.GetFiles(); } }}
這個是載入dll的,然後返回一個Assembly類型的一個反射值,如果該dll中有多個命名空間和類的話,就只用一個Assembly類型的一個反射值即可以完成調用,否則每次產生一個類,都需要反射一次。IO操作相對而言是比較耗費CPU,影響效率的。
using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;namespace DynamicLoadDLL{ /// <summary> /// 載入類 /// </summary> public class LoadClass { private static LoadClass dlc = null; private Type type; private object obj = null; //執行個體 /// <summary> /// 載入dll /// </summary> /// <param name="ass">dll引用</param> /// <param name="nameSpace">類的命名空間</param> /// <param name="classPath">類名稱</param> private LoadClass(Assembly ass, string nameSpace, string classPath) { //載入dll後,需要使用dll中某類. type = ass.GetType(nameSpace + "." + classPath); //利用類型的命名空間和名稱獲得類型 //需要執行個體化類型,才可以使用,參數可以人為的指定,也可以無參數,靜態執行個體可以省略 obj = Activator.CreateInstance(type); //利用指定的參數執行個體話類型 } /// <summary> /// 載入dll /// </summary> /// <param name="ass">dll引用</param> /// <param name="nameSpace">類的命名空間</param> /// <param name="classPath">類名稱</param> public static LoadClass GetInstance(Assembly ass, string nameSpace, string classPath) { if (dlc == null) { dlc = new LoadClass(ass, nameSpace, classPath); } return dlc; } /// <summary> /// 擷取屬性集 /// </summary> /// <returns>返回屬性值</returns> public PropertyInfo[] GetAttrs() { //調用類型中的某個屬性: PropertyInfo[] prop = type.GetProperties(); //通過屬性名稱獲得屬性 //返回屬性集 return prop; } public MethodInfo[] GetMethods() { //調用類型中的方法: MethodInfo[] method = type.GetMethods(BindingFlags.NonPublic); //獲得方法集 //返回方法集 return method; } /// <summary> /// 擷取屬性值 /// </summary> /// <param name="attrName">屬性名稱</param> /// <returns>返回屬性值</returns> public object GetAttrValue(string attrName) { //調用類型中的某個屬性: PropertyInfo prop = type.GetProperty(attrName); //通過屬性名稱獲得屬性 //返回屬性值 return prop.GetValue(obj); } /// <summary> /// 設定屬性值 /// </summary> /// <param name="attrName">屬性名稱</param> /// <returns>返回屬性值</returns> public void SetAttrValue(string attrName, string attrValue) { //調用類型中的某個屬性: PropertyInfo prop = type.GetProperty(attrName); //通過屬性名稱獲得屬性 //返回屬性值 prop.SetValue(obj, attrValue); } /// <summary> /// 執行類方法 /// </summary> /// <param name="methodName">方法名稱</param> /// <param name="paras">參數</param> /// <param name="types">參數類型</param> /// <returns></returns> public object GetMethod(string methodName, object[] paras,Type[] types) { //調用類型中的某個方法: MethodInfo method = type.GetMethod(methodName,types); //通過方法名稱獲得方法 //執行方法 return method.Invoke(obj, paras); } }}
上面這個類根據dll反射值,命名空間和類名,反射出一個具體的類,還提供了屬性和方法的調用方法。很方便。
這些是我在研究外掛程式編程時,順帶研究的,不太深入,但希望對你能有所協助。