在開篇以前我想鄙視我本身一下,這個東西根本不須要去寫,原本已經有東西去實現了,正如我組長說個人,看的開源項目太少了。其實這個東西徹底能夠用ILMerge來解決。函數
而後再說說前言,開發東西久了,總會積累到必定量的Helper或Util,因而都放到一個項目裏面一塊兒編一個dll,用的時候就方便,但是問題來了,像SQLite這種Helper須要帶上它的dll,再多封裝幾個類,附帶的dll就更多了,有時候想單單用一個很簡單的Helper,結果還帶了一大堆不相干的dll,會不爽,並且有種感受是引用時就單純一個Common.dll就夠了,什麼System.Data.SQLite.dll,System.Data.MySql.dll我都不想帶,在一次使用內嵌資源時給流我靈感,把這堆dll在編譯的時候都放到項目資源中,須要的時候就去加載,這樣就好了。學習
單純這個就用到了內嵌資源使用方面的知識,另一個就是AppDomain對dll加載方面的知識。編碼
在使用內嵌資源時,要把資源包含在項目裏面,內嵌的資源在屬性頁面上"生成操做"選擇"潛入資源",spa
在編碼時要把資源用上,得用流來讀取,經過Assembly的GetManifestResourceStream(string name);方法就能夠把資源的流獲取到,流到了就愛幹嗎幹嗎,代碼以下code
1 Stream s = null; 2 byte[] dllDatas = null; 3 try 4 { 5 s = Assembly.GetExecutingAssembly().GetManifestResourceStream("ConsoleApplication2.ClassLibrary1.dll"); 6 dllDatas = new byte[s.Length]; 7 s.Read(dllDatas, 0, dllDatas.Length); 8 } 9 catch (Exception ex) 10 { 11 return null; 12 } 13 finally 14 { 15 if (s != null) 16 { 17 s.Close(); 18 s.Dispose(); 19 } 20 }
dll的流拿到流,使用它的地方就在AppDomain的AssemblyResolve事件,當應用程序域加載外部的程序集時,它會默認往兩個地方找,第一是往.NET Framework的目錄中找,再到應用程序所在目錄中找,因此在默認狀況下咱們開發的類庫都會跟引用程序放到一個目錄,而常常用到的System.dll纔不須要放到引用程序目錄中。那假如須要的dll沒辦法從這兩個地方找到的話,程序會拋出FileNotFoundException異常,這個仍然有辦法解決的,其實在拋出FileNotFoundException異常以前,AppDomain會先觸發AssemblyResolve事件,這個事件會返回這個沒法找到的程序集,返回的程序集爲空,纔會拋FileNotFoundException異常,只要咱們註冊了AssemblyResolve事件,在綁定的方法中把dll從資源中取出來,加載上程序集以後,沒法在文件目錄中找到的程序集就能夠加載到程序域中,程序集中的類能夠照常使用blog
代碼以下事件
1 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 2 3 4 static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 5 { 6 7 Stream s = null; 8 byte[] dllDatas = null; 9 try 10 { 11 s = Assembly.GetExecutingAssembly().GetManifestResourceStream("ConsoleApplication2.ClassLibrary1.dll"); 12 dllDatas = new byte[s.Length]; 13 s.Read(dllDatas, 0, dllDatas.Length); 14 } 15 catch (Exception ex) 16 { 17 return null; 18 } 19 finally 20 { 21 if (s != null) 22 { 23 s.Close(); 24 s.Dispose(); 25 } 26 } 27 Assembly assembly= AppDomain.CurrentDomain.Load(dllDatas); 28 return assembly; 29 }
可是存在一個問題,這個AssemblyResolve事件在封裝的Common項目中註冊比較合適,但是AssemblyResolve事件應該是主動調用的,而Common裏面的類全都是被調用的,我的以爲這個AssemlbyResolve事件能夠放到Helper類的靜態構造函數裏面,此外也暫時想不出更好辦法,或者這種方式自己不是一個好的方式。資源
後續在開發中也發現一個問題,假如這個Common.dll在別的程序集也是經過AssemblyResolve事件被加載到程序域中的時候,這些在Common.dll裏面經過AssemlbyResolve事件加載進來的程序集有問題。此問題還暫時沒法解釋,估計要學習一下CLR方面的知識。開發