3

我正在嘗試編寫一個插件系統,其中程序集可以放在ASP.NET不知道的文件夾中。此插件系統適用於基於ASP.NET MVC的程序集,但對於舊式WebForm程序集(其中.aspx文件Inherits 派生類)System.Web.Compilation.BuildManager負責將.aspx文件編譯爲動態程序集。幫助System.Web.Compilation.BuildManager在未引用的程序集中查找類型

我的問題是BuildManager對我的插件文件夾中的程序集一無所知,似乎完全沒有辦法幫助它。如果我這樣做:

BuildManager.GetType("PluginAssembly.DefinedType", true, true) 

它拋出。如果我第一次進入了Type的引用,然後嘗試:

var instance = BuildManager.CreateInstanceFromVirtualPath(path, type); 

它仍然拋出,即使我現在在特定type通過它需要編譯.aspx文件。有什麼我可以幫助BuildManager找到編譯.aspx文件所需的類型?

更新: 我已經更進了一步,通過調查BuildManager.GetType()實際上做了什麼。通過指定組件的類型(例如「PluginAssembly.DefinedType,PluginAssembly」),然後將自己掛接到事件上,我現在可以找到插件程序集並將其返回,以便BuildManager可以成功構建該類型。這讓下面的工作出色:

BuildManager.GetType("PluginAssembly.DefinedType, PluginAssembly", true, true) 

但是,這仍然不能解決:

var instance = BuildManager.CreateInstanceFromVirtualPath(path, type); 

即使.aspx文件現在在其Inherits指令相同的程序集的引用:

<%@ Page Language="C#"    
     CodeBehind="Index.aspx.cs" 
     Inherits="PluginAssembly.DefinedType, PluginAssembly" %> 

我收到的錯誤是:

「編譯器錯誤信息:CS0234:類型或命名空間名稱「DefinedType」不存在命名空間「PluginAssembly」(?是否缺少程序集引用)」與下列源輸出存在:

Line 205: 
Line 206: [System.Runtime.CompilerServices.CompilerGlobalScopeAttribute()] 
Line 207: public class plugins_pluginassembly_dll_index_aspx 
       : global::PluginAssembly.DefinedType, 
        System.Web.SessionState.IRequiresSessionState, 
        System.Web.IHttpHandler { 
Line 208:   
Line 209:  private static bool @__initialized; 

好像發生了什麼在BuildManager.CreateInstanceFromVirtualPath()內部涉及某個System.Web.Util.IWebObjectFactory,它可能是由於找不到我的程序集而引發此異常。我可以實現這個接口沒有任何問題,但如果我不能告訴BuildManager它有什麼幫助?

+0

添加插件時必須回收應用程序時出現問題? – 2010-04-16 14:24:53

+1

因爲它需要刪除整個網站才能刷新一個插件。此外,它可能不會在中等信任下工作,並且是一個非常糟糕的解決方案。 – 2010-04-22 07:18:00

+0

請注意你正在尋找的答案,但你有沒有試過MEF? http://blogs.msdn.com/hammett/archive/2009/04/23/mef-and-asp-net-mvc-sample.aspx – 2010-04-23 12:00:46

回答

0

我結束了Web Deployment Projects[1]通過預編譯整個Web應用程序分成兩個獨立的組件,然後挖掘到合適的組件,Assembly.GetTypes()實例正確Page對於給定的HTTP請求解決這個。

它使插件開發人員承擔更多的責任,但產生更好的性能,並帶來所有插件完全由ASP.NET編譯器驗證之前在安全敏感和脆弱的)網絡環境。

1

我看到兩種方法可以指定用於編譯頁的組件:

  • 調用BuildManager.AddReferencedAssembly(但我相信你已經嘗試過嗎?)
  • 在編譯頁面的虛擬目錄,把配置所需程序集的列表(在system.web/compilation/assemblies部分),並讓這些程序集在appdomain中可訪問(該框架似乎使用Assembly.Load來查找配置文件中的程序集)。
+0

'BuildManager.AddReferencedAssembly'引發「此方法只能在應用程序的預啓動初始化階段調用」,並且修改web.config不是一個可行的選項,因爲這需要應用程序重新啓動並且模塊要預先知道情況並非總是如此。 – 2010-04-26 10:29:01

1

我不知道你如何能BuildManager負載類型,但嘗試使用AssemblyResolve - 訂閱AppDomain.CurrentDomain.AssemblyResolve事件,以及自己加載程序集和返回(是的,回報)的Assembly實例(或null如果你不認識它)。

並非所有此類代碼都使用與此兼容的方法,但值得一試。

+0

我已經這樣做了,它可以在編譯.aspx.cs文件時解析程序集,但是.aspx文件編譯時會引用'global :: PluginAssembly.DefinedType',它不提供任何解決方法作爲BuildManager的任何程序集假定程序集中已存在程序集。 – 2010-04-26 10:26:38

0

我正在爲ASP.NET自己開發一個延遲加載框架。 您的插件可以在其頁面中始終使用<@ Assembly>指令來手動引用程序集。

相關問題