Почему ASP.NET по-разному разрешает ссылки на сборки? - PullRequest
6 голосов
/ 11 августа 2011

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

Фон

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

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

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

[GAC]

  • 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 Ответ

0 голосов
/ 10 февраля 2012

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

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

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

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

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

...