为什么ASP.NET以不同方式解析汇编引用?

Per*_*son 6 asp.net gac assembly-references assemblyresolve

我真的很努力找到一个类似的问题来获得一些线索,但似乎没有人描述我们所拥有的情况,所以在这里.

背景

我们的产品具有以下一般设计:

[本地安装文件夹]

  • 包含一组.NET程序集,实现了我们的大部分产品功能.
  • 示例:Implementation1.dll,Implementation2.dll

[GAC]

  • ClientAPI.dll.我们的客户端程序集,将从最终用户Visual Studio项目中引用.对本地安装文件夹中的实现dll有强烈的引用.

在ClientAPI.dll中,我们有一个入口点,我们需要调用最终用户项目.让我们来称呼它Initialize().

我们首先要做的Initialize是使用事件在当前域上安装所谓的程序集解析处理程序AssemblyResolve.这个处理程序将知道如何定位实现dll并使用它们将它们加载到客户端进程中Assembly.Load().

考虑控制台应用程序.它看起来像:

class Class1
{
    void Main(string[] args)
    {
        ClientAPI.Initialize();

        // Use other API's in the assembly, possibly internally referencing the
        // implementation classes, that now will be resolved by our assembly
        // resolve handler.
    }
 }
Run Code Online (Sandbox Code Playgroud)

现在,在控制台/ Windows窗体/ WPF世界中一切都很好.我们的程序集解析处理程序已正确安装和调用,一旦ClientAPI.dll需要其功能,它就可以成功解析对实现DLL的引用.

问题陈述

话虽如此,我们打算不仅支持控制台或WPF应用程序,因此我们依赖于ASP.NET中的相同设计.因此,在VS 2010中创建一个新的ASP.NET Web应用程序项目,我们认为一切都会像以下一样简单:

class Globals : HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        ClientAPI.Initialize();

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

在ASP.NET运行时世界中停留了几个20-30小时,在开发服务器和IIS中尝试上述操作,我们已经了解到那些事情并不像我们预期的那样.

事实证明,在ASP.NET中,只要在ClientAPI任何地方引用类,就会立即解析它对任何其他程序集的所有引用.不仅如此:结果被缓存(通过设计,因为我们已经发现了.NET 2.0),这意味着我们从来没有机会尝试协助CLR.

如果不进一步阐述我们尝试和学过的不同事物,它基本上归结为我们所拥有的这个问题:

为什么ASP.NET解析这样的引用?它与其他类型的应用程序的工作方式不兼容,甚至更多,它不是根据.NET/CLR运行时的文档,指定在首次需要时解析对外部类型/程序集的引用(即首先在代码中使用).

任何形式的见解/想法都将受到高度赞赏!

Spi*_*keh 0

Windows 窗体/WPF 应用程序在单独的客户端计算机上运行(因此在单个本地上下文中运行),而 ASP.Net 在 IIS 内、应用程序池内、服务器或服务器组上运行(在网络场情况下)。加载到应用程序池中的任何内容都可供整个应用程序使用(因此在连接到该应用程序的所有客户端之间共享)。

HttpApplication.Application_Start在应用程序启动时执行一次。它不像 Winforms 应用程序那样针对每个客户端执行 - 如果您需要为每个连接的客户端初始化某些内容,请使用 Session_Start 或 Session_OnStart,但随后您可能会遇到服务器内存问题,具体取决于客户端的数量将连接到您的网络应用程序。这还取决于您的类是否是单例,以及 Initialize() 方法是否是静态的。如果您遇到其中任何一种情况,您将很快遇到跨线程问题。

此外,值得注意的是,空闲的 IIS 应用程序池在一段时间后会自行重置。例如,如果没有人过夜使用 Web 应用程序,IIS 将刷新应用程序的应用程序池并释放内存。这些设置可以在 IIS 管理中更改,但这样做时应该小心 - 更改这些设置以规避设计不当的对象(或不是为 Web 应用程序设计的对象)可能会产生更多问题。

仅供参考 - 我有点挑剔,但为了避免怀疑,该对象没有被缓存- 是的,它被加载到内存中,但内存的管理方式取决于您设计对象的方式(缓存在网络世界中是完全不同的事情,并且可以在应用程序的许多不同层中实现)。

不要尝试让 Web 应用程序表现得像 Windows 应用程序;你只会给自己制造更多的问题!