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

时间:2011-08-11 12:13:09

标签: asp.net gac assembly-references assemblyresolve

我真的很努力找到一个类似的问题来获得一些线索,但似乎没有人描述我们所拥有的案例,所以就这样了。

背景

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

[本地安装文件夹]

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

[GAC]

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

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

我们在Initialize中做的第一件事就是使用AssemblyResolve事件在当前域上安装所谓的程序集解析处理程序。该处理程序将知道如何使用Assembly.Load()找到实现dll并将它们加载到客户端进程中。

考虑一个控制台应用程序。它看起来像:

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.
    }
 }

现在,在控制台/ 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();

        // ...
    }
}

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

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

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

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

仅供参考 - 我有点挑剔,但为了避免疑问,该对象缓存 - 是的,它被加载到内存中,但是如何管理内存如何设计对象(在Web世界中缓存是完全不同的事情,可以在应用程序的许多不同层中实现)。

不要试图使Web应用程序像Windows应用程序一样;你只会给自己制造更多问题!