問題的提出:
在某些應用中往往會遇到這樣的情況,例如最近遇到一個應用大致需要做這樣的事情:
1.有幾個比較類似的業務,但是每個的處理方法和輸出不同;
2.需要動態處理這些業務,例如某個時間可能需要處理甲業務,某個時間需要處理乙業務;
3.需要處理的業務數量不確定,隨時可能有增減情況;
4.希望主體程式比較固定;
問題的分析:
我的想法是將這些業務規範為一些類庫,固定好規範的介面。然後將這些Dll統一放在某個目錄下面,目錄中的Dll可以採取簡單的XCopy方式來增刪,並且需要保證主體程式不會長時間佔用某個Dll資源,調用完就釋放。
解決方案實驗:
先將主要技術關鍵點抽取出來,關鍵就是建立一個可以動態調用某個目錄下面的Dll中的某個方法的機制,因此先做一些簡單的測試,將這個機制的建立弄清晰。
下面是這個簡單的機制:
先建立了三個簡單的類庫,ADll,BDll,CDll。主體調用程式是testReadDll,它需要調用相對目錄Dlls下面的全部Dll中的makeStr,沒有輸出錯誤資訊繼續執行下一個Dll。其中ADll和BDll都有類似的介面(這裡並沒有將介面抽象出來),但CDll為了測試,並沒有實作類別似的介面。
假設ADll和BDll實現了方法makeStr,CDll沒有實現這個方法。
由於.NET的強大的反射機制,實現這些功能並不困難。
主體程式中調用Dll指定方法的代碼:
private void btnInvoke_Click(object sender, System.EventArgs e)
{
lstValue.Items.Clear();
DirectoryInfo d = new DirectoryInfo("Dlls"); // 目錄和當前EXE在同一個目錄下
foreach (FileInfo file in d.GetFiles("*.dll"))
{
string pathName = d.FullName + "\" + file.Name;
// 根據檔案名稱擷取程式集資訊
Assembly assembly = Assembly.LoadFrom(pathName);
lstValue.Items.Insert(0,assembly.FullName + "的調用結果:");
try
{
foreach (Type t in assembly.GetTypes())
{
Object obj = t.InvokeMember(null,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance,
null,null,null);
string s = (string)t.InvokeMember("makeStr",
BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
null,obj,null);
lstValue.Items.Insert(0,s);
}
}
catch (Exception ex)
{
lstValue.Items.Insert(0,ex.ToString());
}
}
}
ADll相關代碼:using System;
namespace ADll
{
/// <summary>
/// Class1 的摘要說明。
/// </summary>
public class AClass
{
public AClass()
{
//
// TODO: 在此處添加建構函式邏輯
//
}
public string makeStr()
{
string retStr;
retStr = "ADll make String";
return retStr;
}
}
}
BDll相關代碼:using System;
namespace BDll
{
/// <summary>
/// Class1 的摘要說明。
/// </summary>
public class BClass
{
public BClass()
{
//
// TODO: 在此處添加建構函式邏輯
//
}
public string makeStr()
{
string retStr;
retStr = "BDll make StringModifyAdd..ok2";
return retStr;
}
}
}
CDll相關代碼:using System;
namespace CDll
{
/// <summary>
/// Class1 的摘要說明。
/// </summary>
public class CClass
{
public CClass()
{
//
// TODO: 在此處添加建構函式邏輯
//
}
public string makeStr2()
{
string retStr;
retStr = "cDll make StringModify";
return retStr;
}
}
}
機制測試:
1.先將ADll,BDll編譯通過放到Dlls下面,運行testReadDll調用makeStr結果如下:
2.不需要退出testReadDll,將ADll刪除,運行testReadDll調用makeStr結果如下:
3.不需要退出testReadDll,將ADll和CDll再次放入Dlls,運行testReadDll調用makeStr結果如下:
4.那麼如果ADll和BDll增加一個副本又如何呢?
不需要退出testReadDll,為ADll和BDll增加一個副本在Dlls如:
運行testReadDll調用makeStr結果如下:
小結:
由此可以看出,這樣的機制是十分靈活的,只要將業務相關的Dll放入這個目錄下面就可以了。
另外,對於副本的調用結果是一樣的,當然這些可以在程式中再做一些限制,避免重複調用。
調用的順序和時間規則也可以在程式中做定義或者用一個設定檔來限制。
這裡下載相關代碼。