3

我正在尝试编写一个插件系统,可以将程序集放在 ASP.NET 不知道的文件夹中。这个插件系统适用于基于 ASP.NET MVC 的程序集,但对于老式的 WebForm 程序集(其中的.aspx文件InheritsSystem.Web.UI.Page派生类)System.Web.Compilation.BuildManager负责将.aspx文件编译成动态程序集。

我的问题是BuildManager我对插件文件夹中的程序集一无所知,而且我似乎完全无能为力。如果我做:

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

它抛出。如果我首先得到参考Type然后尝试:

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

即使我现在已经传入了type编译.aspx文件所需的具体内容,它仍然会抛出。我能做些什么来帮助BuildManager找到编译.aspx文件所需的类型吗?

更新:BuildManager.GetType()通过研究实际做 了什么,我更进了一步。通过指定定义类型的程序集(例如“PluginAssembly.DefinedType,PluginAssembly”),然后将自己挂钩到System.AppDomain.CurrentDomain.AssemblyResolve事件中,我现在可以找到插件程序集并将其返回,以便 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:名称空间“PluginAssembly”中不存在类型或名称空间名称“DefinedType”(您是否缺少程序集引用?)”,源输出如下:

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呢?

4

4 回答 4

1

我看到有两种方法可以指定用于编译页面的程序集:

  • 调用 BuildManager.AddReferencedAssembly (但我假设你已经尝试过那个?)
  • 在编译页面的虚拟目录配置中放入所需程序集的列表(在 system.web/compilation/assemblies 部分中)并在 appdomain 中访问这些程序集(框架似乎使用 Assembly.Load 来查找在配置中找到的程序集文件)。
于 2010-04-23T13:25:25.530 回答
1

我不知道如何BuildManager加载类型,但您可以尝试使用AssemblyResolve- 订阅AppDomain.CurrentDomain.AssemblyResolve事件,并自己加载程序集并返回(是的,返回)Assembly实例(或者null如果您不认识它)。

并非所有此类代码都使用与此兼容的方法,但值得一试。

于 2010-04-26T05:17:40.680 回答
0

我最终通过Web 部署项目 [1]解决了这个问题,方法是将整个 Web 应用程序预编译为两个单独的程序集,然后深入研究正确的程序集,为给定的 HTTP 请求Assembly.GetTypes()实例化正确的程序集。Page

它使插件开发人员承担了更多责任,但产生了更好的性能,并带来了额外的好处,即所有插件在(安全敏感和脆弱的)Web 上下文中执行之前由 ASP.NET 编译器完全验证.

于 2010-04-26T17:08:28.870 回答
0

我自己正在为 ASP.NET 开发一个延迟加载框架。您的插件始终可以<@ Assembly>在其页面中使用该指令来手动引用程序集。

于 2012-08-02T18:09:13.057 回答