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>指令来手动引用程序集。

相关问题