ASP.NET Web Froms开发模式中实现程序集的延迟加载
延遲加載是一個很大的誘惑,可以達(dá)到一些比較好的效果,比如:
1、在實體框架中,由于關(guān)聯(lián)數(shù)據(jù)的數(shù)量和使用時機是不確定的,通過延遲加載,僅在使用的時候去執(zhí)行關(guān)聯(lián)數(shù)據(jù)的查詢操作,減少無謂的數(shù)據(jù)查詢操作,可以降低單次數(shù)據(jù)查詢執(zhí)行的時間,提升系統(tǒng)的性能。
2、在一個插件平臺中啟動平臺時只加載必需的程序集,當(dāng)執(zhí)行到具體插件時再加載插件相關(guān)的程序集,僅在需要的時候加載資源,可以減少插件平臺的啟動時間,使內(nèi)存的占用更合理些。
延遲加載可以使資源的占用更加合理,并提升一定的性能,當(dāng)然也有一些例子來說明延遲加載的壞處,這就需要根據(jù)實際的情況去考量,不是這篇文章的目的。
?
言歸正傳,在ASP.NET Web Forms開發(fā)模式中,程序集一般都放到bin目錄下,或者在web.config中通過配置codebase或者probing節(jié)點指定程序集目錄,應(yīng)用程序啟動時會從這些位置自動加載程序集。我們要使用延遲加載,就不能將程序集放到這些地方,將需要延遲加載的程序集放到一些有規(guī)則可循的目錄是一種比較好的方式。比如:
root
|–bin
|–lazyload
| ? ?|–bin1
| ? ?|–bin2
將這些程序集都放到一個lazyload的目錄中,然后在其中根據(jù)程序集的劃分建立不同的子目錄,根據(jù)需要去不同的目錄中加載程序集。
?
那么使用什么方法加載程序集呢?
Assembly類提供了幾個靜態(tài)方法:Load、LoadFile、LoadFrom,可以通過這幾個方法將dll文件加載到當(dāng)前應(yīng)用程序域的程序集中。
關(guān)于這幾個方法如何選擇,網(wǎng)上有一些總結(jié),這里不做討論。以下是一些總結(jié):
http://www.cnblogs.com/xuqingfeng/archive/2012/05/22/assembly-load-loadfrom-loadfile-details.html
http://msdn.microsoft.com/zh-cn/library/dd153782(v=vs.110).aspx
?
實現(xiàn)程序集的延遲加載需要擴展兩個地方:
1、依賴程序集的延遲加載
通過訂閱當(dāng)前應(yīng)用程序域的AssemblyResolve事件,應(yīng)用程序域在加載依賴程序集時如果找不到就會觸發(fā)這個事件。
在這個事件中我們可以通過一些規(guī)則找到需要加載的程序集文件,然后通過Assembly的加載方法加載到內(nèi)存,并返回。
| AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; |
| ? |
| private?Assembly CurrentDomain_AssemblyResolve(object?sender, ResolveEventArgs args) |
| { |
| Assembly assembly =?null; |
| ? |
| //加載程序集部分省略 |
| ? |
| return?assembly; |
| } |
2、頁面動態(tài)編譯所需程序集的延遲加載
aspx頁面在首次訪問時會進(jìn)行編譯,編譯時需要頁面綁定的類所在的程序集。默認(rèn)情況下這些程序集是在程序啟動的時候自動加載的,從.net4開始,微軟提供了一個應(yīng)用程序啟動的擴展支持System.Web.PreApplicationStartMethod,也可以在這里通過程序加載程序集,但還是達(dá)不到延遲加載的效果。
aspx頁面的編譯是通過BuildManager實現(xiàn)的,調(diào)用BuildManager.AddReferencedAssembly方法可以添加程序集,但是這個方法只能在上邊提到的擴展支持中調(diào)用,程序啟動后再調(diào)用就會拋出異常(可能是.net4.0還有些東西沒協(xié)調(diào)好),此路不通。既然不能通過方法添加,那是不是可以直接加入到BuildManager的程序集集合中,很不幸全是私有的,有興趣的可以自己反編譯看看。
私有的其實也不是沒有辦法可以獲取,使用反射,還好BuildManager有一個靜態(tài)的屬性TheBuildManager,通過反射獲取這個屬性的值就可以得到內(nèi)部的BuildManager實例,修改程序集的集合就不成問題了。
| // 獲取BuildManager的實例 |
| PropertyInfo buildmanagerProperty = Type.GetTypeFromHandle(typeof(BuildManager).TypeHandle).GetProperty("TheBuildManager", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty); |
| BuildManager buildmanager = buildmanagerProperty.GetValue(null,?null)?as?BuildManager; |
| ? |
| // 獲取TopLevelReferencedAssemblies |
| PropertyInfo topLevelReferencedAssembliesProperty = Type.GetTypeFromHandle(typeof(BuildManager).TypeHandle).GetProperty("TopLevelReferencedAssemblies", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty); |
| IList assemblies = topLevelReferencedAssembliesProperty.GetValue(buildmanager,?null)?asIList; |
| ? |
| // 添加程序集 |
| Assembly assembly =?null; |
| ? |
| //加載程序集部分省略 |
| ? |
| assemblies.Add(assembly); |
這段程序要在頁面編譯之前調(diào)用,比如PageHandlerFactory的GetHandler方法中。
?
通過這兩個擴展基本上就可以實現(xiàn)程序集的延遲加載了,能用來干什么就要看自己了。博客園有個人搞了個OSGI.NET,就用到文中的兩個方法。
當(dāng)然上邊只是初步給出了解決問題的方法,如果要實際使用,可能要考慮更多的問題,比如多線程同步問題、程序集多版本問題等等,有興趣的可以寫寫看。
?
本人獨立博客地址:http://blog.bossma.cn/dotnet/asp-net-how-to-lazy-load-assembly/
轉(zhuǎn)載請注明出處。
?
轉(zhuǎn)載于:https://www.cnblogs.com/bossma/p/3457903.html
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Web Froms开发模式中实现程序集的延迟加载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: xposed 修改手机定位
- 下一篇: 在高科技产业当中,有时候你的产品出现了问