Я действительно изо всех сил пытался найти похожую проблему, чтобы получить некоторые зацепки, но, похоже, никто не описывает случай, который у нас есть, так что вот оно.
Фон
У нас есть продукт со следующим общим дизайном:
[Локальная папка установки]
- Содержит набор сборок .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.
}
}
Теперь все хорошо в мире консоли/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, указывающей, что ссылки на внешние типы/сборки должны разрешаться при первой необходимости (т.е. когда впервые используется в коде).
Любое понимание/идеи будут высоко оценены!