Почему ASP.NET по-разному разрешает ссылки на сборки?

Я действительно изо всех сил пытался найти похожую проблему, чтобы привлечь некоторых клиентов, но никто, кажется, не описывает описанный нами случай, так что вот так.

Фон

У нас есть продукт со следующим общим дизайном:

[Локальная папка установки]

  • Содержит набор сборок.NET, реализующих основную часть функциональности нашего продукта.
  • Пример: Реализация1.dll, Реализация2.dll

[ПКК]

  • ClientAPI.dll. Наша клиентская сборка, на которую нужно ссылаться из проектов Visual Studio конечного пользователя. Имеет сильные ссылки на реализацию DLL в локальной папке установки.

В ClientAPI.dll у нас есть точка входа, для запуска которой требуются проекты конечного пользователя. Давай называть это Initialize(),

Самое первое, что мы делаем в Initialize установить так называемый обработчик разрешения сборки в текущем домене, используя AssemblyResolve событие. Этот обработчик будет знать, как найти библиотеки реализации и загрузить их в клиентский процесс, используя 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.
    }
 }

Теперь все хорошо в мире консоли / Windows Forms/WPF. Наш обработчик разрешения сборки правильно установлен и вызван, и он может успешно разрешать ссылки на библиотеки DLL реализации, когда ClientAPI.dll требует их функциональности.

Постановка задачи

С учетом вышесказанного мы намерены не поддерживать только консольные или WPF-приложения, поэтому мы полагались на тот же дизайн в ASP.NET. Следовательно, создав новый проект веб-приложения ASP.NET в VS 2010, мы решили, что все будет так же просто, как:

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

        // ...
    }
}

За 20-30 часов пребывания во вселенной времени выполнения ASP.NET, попробовав вышесказанное как на сервере разработки, так и в IIS, мы поняли, что на самом деле все не так, как мы ожидали.

Оказывается, в ASP.NET, как только ClientAPI ссылка на класс в любом месте, все ссылки, которые он имеет на любые другие сборки, немедленно разрешаются. И не только это: результаты кэшируются (по замыслу, начиная с.NET 2.0, которую мы обнаружили), а это означает, что у нас никогда не было шансов вообще помочь CLR.

Без дальнейшей проработки различных вещей, которые мы попробовали и изучили, все сводится к следующему вопросу:

Почему ASP.NET разрешает ссылки так? Это несовместимо с тем, как это делают другие типы приложений, и, более того, это не соответствует документации среды выполнения.NET / CLR, в которой указывается, что ссылки на внешние типы / сборки должны разрешаться при первой необходимости (т.е. когда впервые используется в коде).

Любые идеи / идеи будут высоко оценены!

1 ответ

Приложения Windows Forms / WPF выполняются на отдельных клиентских компьютерах (и, следовательно, выполняются в одном локальном контексте), тогда как ASP.Net работает в IIS, в пуле приложений, на сервере или наборе серверов (в ситуации веб-фермы). Все, что загружено в пул приложений, доступно всему приложению (и поэтому распределяется между всеми клиентами, которые подключаются к приложению).

HttpApplication.Application_Start выполняется один раз, когда приложение запускается. Он не выполняется для каждого клиента, как это было бы с приложением Winforms - если вам нужно что-то инициализировать для каждого подключаемого клиента, используйте Session_Start или Session_OnStart, но затем вы можете столкнуться с проблемами памяти на сервере, в зависимости от того, сколько клиентов собираетесь подключиться к вашему веб-приложению. Это также зависит от того, является ли ваш класс одноэлементным, и является ли метод Initialize() статическим. Если у вас возникнет какая-либо из этих ситуаций, вы довольно быстро столкнетесь с проблемами многопоточности.

Кроме того, стоит отметить, что неиспользуемый пул приложений IIS будет сброшен через некоторое время. Например, если никто не использует веб-приложение в одночасье, IIS очистит пул приложений и освободит память. Эти параметры можно изменить в рамках администрирования IIS, но при этом следует соблюдать осторожность - изменение этих параметров для обхода плохо спроектированного объекта (или объекта, не предназначенного для веб-приложения) может создать еще больше проблем.

К вашему сведению - я немного суетлив, но во избежание сомнений, объект не кэшируется - да, он загружается в память, но как управление памятью зависит от того, как вы спроектировали объект (кэширование в веб-мире это совсем другое дело, и может быть реализовано на разных уровнях вашего приложения).

Не пытайтесь заставить веб-приложение вести себя как приложение для Windows; вы просто создадите себе больше проблем!

Другие вопросы по тегам