代码之家  ›  专栏  ›  技术社区  ›  Asbjørn Ulsberg

帮助system.web.compilation.buildmanager在未引用的程序集中查找类型

  •  3
  • Asbjørn Ulsberg  · 技术社区  · 14 年前

    我正在尝试编写一个插件系统,在该系统中,可以将程序集放在asp.net不知道的文件夹中。这个插件系统对于基于asp.net mvc的程序集很好,但是对于老式的webform程序集(其中 .aspx 文件夹 Inherits 这个 System.Web.UI.Page 派生类) System.Web.Compilation.BuildManager 负责编制 ASPX 文件到动态程序集中。

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

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

    它扔了。如果我第一次得到 Type 然后尝试:

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

    尽管我已经通过了 type 它需要编译 ASPX 文件。有什么我能帮忙的吗 建筑经理 找到编译 ASPX 文件?

    更新: 我更进一步,通过调查 BuildManager.GetType() 实际上是的。通过指定在中定义类型的程序集(例如“pluginassembly.definedType,pluginassembly”),然后将自己连接到 System.AppDomain.CurrentDomain.AssemblyResolve 事件,我现在可以找到插件程序集并返回它,以便BuildManager可以成功构造类型。这将使以下操作与飞行颜色一起工作:

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

    然而,这仍然失败了:

    var instance=buildmanager.createInstanceFromVirtualPath(路径,类型);
    

    即使 ASPX 文件中现在有相同的程序集引用 继承 指令:

    <%@ 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 它可能是由于找不到我的程序集而引发此异常的原因。我可以毫无问题地实现这个接口,但是如果我不能告诉 建筑经理 关于它?

    4 回复  |  直到 12 年前
        1
  •  1
  •   Shtong    14 年前

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

    • 调用buildmanager.addreferencedAssembly(但我认为您已经尝试过了?)
    • 将所需程序集的列表(在system.web/compilation/assemblies部分)放入编译页的虚拟目录配置中,并在appdomain中访问这些程序集(框架似乎使用assembly.load查找在配置文件中找到的程序集)。
        2
  •  1
  •   Marc Gravell    14 年前

    我不知道怎么做 BuildManager 加载类型,但您可以 尝试 使用 AssemblyResolve -订阅 AppDomain.CurrentDomain.AssemblyResolve 事件,然后自己加载程序集并返回(是,返回) Assembly 实例(或) null 如果你认不出来的话)。

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

        3
  •  0
  •   Asbjørn Ulsberg    14 年前

    我最终解决了这个问题 Web Deployment Projects [1] 通过将整个web应用程序预编译为两个独立的程序集,然后使用 Assembly.GetTypes() 实例化正确的 Page 对于给定的http请求。

    它让插件开发人员承担了更多的责任,但也带来了更好的性能,额外的好处是,在所有插件在(安全敏感和脆弱的)web上下文中执行之前,它们都要经过asp.net编译器的完全验证。

        4
  •  0
  •   Marijn    12 年前

    我自己正在为asp.net开发一个延迟加载框架。 您的插件总是可以使用 <@ Assembly> 在其页中手动引用程序集的指令。