ASP.NET 如何動態載入組件(Assembly)

如果你的 IIS 中有許多相關站台、網站、或 Web,但每個不同的網站都會使用到相同組件的話,通常的作法是將該組件註冊進 GAC ( Global Assembly Cache )。我最近就在想有沒有辦法就將組件放在特定目錄下,然後所有的 ASP.NET 就動態載入這個目錄中的特定幾個共用的組件,以下是研究的心得分享。

我將整個過程分成「開發階段」與「部署階段」,並假設以下情境:

  • 假設共用的組件檔名為 "ShareCL.dll"。
  • 部署階段時要將 ShareCL.dll 放一份到特定目錄下,假設共用的目錄為 "D:\ShareDLL\"。

開發階段

在開發階段的時候,那些共用的組件一樣放到各專案的 bin 目錄下,所以在 Visual Studio 中開發的時候,一樣可以享用 Intellisense 的好處,整個開發過程就跟平常開發時一樣。

但由於我們將網站部署到正式主機時,組件並不在各網站的 bin 目錄下,而是在共用的目錄裡,這時就會發生組件解析失敗的錯誤:

無法載入檔案或組件 'ShareCL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 或其相依性的其中之一。 系統找不到指定的檔案。

我們只要修改 Global.asax 的 Application_Start() 事件中的程式碼,告訴 AppDomain 在解析/找尋組件失敗的時候,要特別去我指定的地方載入共用的組件,我們要靠的是 AppDomain.AssemblyResolve 事件:

protected void Application_Start() {
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyAssemblyResolver);
}

static Assembly MyAssemblyResolver(object sender, ResolveEventArgs args) {
    AppDomain domain = (AppDomain)sender;
    byte[] rawAssembly = System.IO.File.ReadAllBytes(@"D:\ShareDLL\ShareCL.dll");
    byte[] rawSymbolStore = System.IO.File.ReadAllBytes(@"D:\ShareDLL\ShareCL.pdb");
    Assembly assembly = domain.Load(rawAssembly, rawSymbolStore);
    return assembly;
}

加上這段程式碼之後,當網站應用程式找不到我們的共享組件時,就會自動到 D:\ShareDLL\ShareCL.dll 動態載入組件了,而且也只有「找不到」組件時才會執行這個事件方法,因此並不會影響開發作業。

部署階段

部署網站時就可以不用再針對每個網站更新 bin 目錄下的組件了,只要將組件更新到共享的組件目錄中即可。

不過由於組件是在 Application-Level 載入的,所以就算你更新了網站中的組件,事實上也不會立即生效,而是當應用程式重新啟動時才會重新載入更新過的組件,這部分可以透過重新啟動 IIS 中的應用程式集區(Application Pool)即可達到此需求。

如果你想列出目前 AppDomain 所載入的組件有哪些,可以用以下程式碼取得:

Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

foreach (Assembly assembly in assemblies)
{
    Response.Write(assembly.FullName + "<br/>");
}

相關連結

  

此文章由 will 發表於 2008/12/28 下午 09:49:19

永久連結 | 評論 (3) | 此文章的RSSRSS comment feed |

分類: .Net | ASP.NET

標籤: ,

收藏:

相關文章

評論

十二月 29. 2008 09:49

blogger

那請問一下
如果我所有的要用到的組件
都不在 GAC 也不在 BIN 下面
全都放在 ShareDLL 目錄
也可以這樣用嗎?
另外如果是 WinForm Application 的話
是否也採取一樣的做法?
謝謝您的文章
好多都很受用唷 Laughing

blogger tw

十二月 29. 2008 10:20

will

1. 可以啊!

2. WinForm Application 與 Console Application 我也曾經嘗試過,但好像動態載入的組件都一定要透過 Reflection 才能使用,沒辦法像 ASP.NET 這麼方便的樣子。
我有到 MSDN 討論區發問,看看這幾天會不會有人回答:http://tinyurl.com/a63ltr

will tw

一月 4. 2009 23:41

tomexou

msdn論壇有兩位回文,第1則講plugin方式,但它僅觸發單一method而己,不符合這題目的載入動作。第2則講dll的路徑,說loadfrom與loadfile的不同,我試了一下也沒用。google上的文章大都講動態觸發單一method的方式,直到現在,我還沒發現真正的解答。

tomexou tw

新增評論


(將顯示您的Gravatar圖示)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



線上預覽

七月 4. 2009 21:17