这真的让我很生气.开始:
我的目标是在运行时加载包含嵌入式aspx,ascx等的程序集.我还想不将程序集文件锁定在磁盘上,这样我就可以在运行时更新该文件而不必重新启动应用程序(我知道这将保留以前的版本).
为此,我编写了一个可以解决问题的虚拟路径提供程序.我已订阅CurrentDomain.AssemblyResolve事件,以便将框架重定向到我的程序集.
问题是当框架尝试为aspx页面编译动态程序集时,我得到以下信息:
编译器错误消息:CS0400:在全局名称空间中找不到类型或名称空间名称’Pages'(是否缺少程序集引用?)
源错误:
公共类app_resource_pages__version_1_0_0_0__culture_neutral__publickeytoken_null_default_aspx:global :: Pages._Default,System.Web.SessionState.IRequiresSessionState,System.Web.IHttpHandle
我注意到,如果我用Assembly.Load(AssemblyName)或Assembly.LoadFrom(filename)加载程序集,则不会得到上述错误.如果我用Assembly.Load(byte [])加载它(以便不锁定它),则会引发异常,但我的AssemblyResolve处理程序在被调用时会正确返回程序集(被调用一次).
所以我猜想它在框架解析asp标记时被调用一次,而在它试图为aspx页面创建动态程序集时不被调用.
解决方法:
我不确定是什么导致缺少程序集引用,但是如果我们稍微退后一步,使程序按预期工作,那么我们必须解决另一个问题.这个问题是加载组件的锁定. .Net框架始终锁定加载的程序集.您可以更新bin文件夹中的dll文件的原因实际上是一个技巧.您会看到,AppDomain具有一个名为ShadowCopyDirectories的不错的属性,该属性指示在加载程序集时将被阴影复制的目录.因此,通过更改影子复制的目录列表,您可以从任何文件夹加载而不锁定程序集:
protected const string ApplicationAssembliesFolder = "~/Assemblies";
protected void Application_Start(object sender, EventArgs e)
{
var assembliesPath = Server.MapPath(ApplicationAssembliesFolder);
AppDomain.CurrentDomain.SetShadowCopyPath(
AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories +
Path.PathSeparator + assembliesPath);
Assembly.LoadFrom(
Path.Combine(assembliesPath, "Example.dll"));
}