Сборка недоступна после изменения Web.config - PullRequest
8 голосов
/ 03 апреля 2010

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

GetTypeByName - моя служебная функция, которая просто перебирает Thread.GetDomain().GetAssemblies(), а затем выполняет assembly.GetType(fullName), чтобы найти соответствующий тип. Очевидно, этот результат кэшируется для дальнейшего использования и скорости.

Однако у меня возникают некоторые проблемы, из-за которых при обновлении файла web.config (и, в некоторых более редких случаях, если пул приложений перезапускается), он теряет все знания об определенных сборках, что приводит к невозможности визуализации экземпляр типа модуля. Отладка показывает, что отсутствующая сборка буквально не существует в текущем списке сборок потока.

Чтобы обойти это, я добавил вторую проверку, которая немного грязная, но повторяется через DLL-каталог / bin / и проверяет, что каждая из них существует в списке сборок. Если это не так, он загружает его с помощью Assembly.Load и исправляет проблему с контекстом благодаря «Решение проблемы с контекстом загрузки сборки» .

Это будет работать, только кажется, что (и я знаю, что это не должно быть возможно), некоторые проекты по-прежнему имеют доступ к отсутствующей сборке, например, мой настоящий веб-проект, а не сам фреймворк, и затем он жалуется что дубликаты ссылок были добавлены!

Кто-нибудь когда-нибудь слышал о чем-либо подобном или у кого-нибудь есть идеи, почему сборка просто перестает существовать при изменении конфигурации? Если не считать решения, какой самый элегантный обходной путь для перезагрузки всех сборок в корзине? Это должно быть все в одном «хите», чтобы посетители сайта не видели никакой разницы, кроме небольшой задержки, поэтому файл app_offline.htm исключен. Программное переименование DLL в корзине и последующее присвоение ей имени работает, но требует разрешения «изменить» для учетной записи пользователя IIS, что безумие.

Спасибо за любые советы, которые может собрать сообщество!

Ответы [ 5 ]

2 голосов
/ 12 апреля 2010

Как правило, вам не следует полагаться на то, какие сборки загружаются в данный момент в домене приложения, поскольку это происходит динамически. Вместо этого просто вызовите System.Web.Compilation.BuildManager.GetType () вместо Type.GetType () или Assembly.GetType (). Это должно просто сделать правильную вещь для вас и не зависеть от циклов appdomain.

2 голосов
/ 06 апреля 2010

Как вы, очевидно, знаете, существует много ситуаций, когда текущий домен приложения выгружается и перезагружается . После каждой перезагрузки все сборки выгружаются, и все приложение запускается «с нуля».

Сборки по умолчанию загружаются по требованию. Обычно это тот случай, когда JIT натыкается на какую-то ссылку. Как следствие, перезагрузка домена приложения очистит сборки в домене приложения, и они появятся только позже, когда JIT загрузит их.

В качестве решения я вернусь к использованию статического метода Type.GetType() и предоставлю квалифицированное имя сборки (например, имя типа с включенным именем сборки). Это то же самое, что фреймворк использует при загрузке типов, указанных в файле конфигурации, и он гарантирует, что требуемая сборка будет найдена и загружена по требованию, без каких-либо хитростей. См. Раздел примечаний метода выше (имя метода над именем является ссылкой).

Для этого потребуется обновить базу данных, чтобы она содержала полные имена сборок вместо «только» полных полных имен типов. Однако это также гарантирует, что вы не столкнетесь с конфликтами имен, когда две сборки предоставляют разные типы с одним и тем же именем, так что в любом случае это хорошая идея.

1 голос
/ 06 апреля 2010

У меня похожая проблема, когда я обновляю 2-5 файлов, ether web.config, ether другие файлы, и asp.net необходимо воссоздать запущенные файлы, то иногда не удается найти некоторые классы / функции, которые существуют на DLL-файлы, и моя система не работает - выкиньте ошибки, подобные вашей.

Мое решение заключается в том, что я помещаю app_offline.htm в корень, делаю свои обновления, затем переименовываю / удаляю app_offline.htm, и моя система работает нормально.

Я уверен, что это как-то связано с кэшированными скомпилированными файлами, но у меня не было тщательного поиска, что именно вызвало это.

[что является самым элегантным решением для перезагрузки всех сборок в корзине]

Теперь самый элегантный обходной путь - это вызвать HttpRuntime.UnloadAppDomain и фактически остановить приложение и запустить его снова.

http://msdn.microsoft.com/en-us/library/system.web.httpruntime.unloadappdomain(VS.80).aspx

Я не знаю, решит ли это вашу проблему, вам нужно сделать тесты.

вероятно, на Global.asax сделать что-то подобное

void Application_Error(object sender, EventArgs e) 
{
   Exception ex = Server.GetLastError().GetBaseException();
   ...if ex is your error, and you get more than 2 ...
   {
     HttpRuntime.UnloadAppDomain();
   }
}
1 голос
/ 03 апреля 2010

Я никогда раньше не слышал об этой проблеме.

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

см .: http://msdn.microsoft.com/en-us/library/823z9h8w(VS.80).aspx

пример:

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="bin;bin2\subbin;bin3"/>
      </assemblyBinding>
   </runtime>
</configuration>
0 голосов
/ 09 апреля 2010

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

var temp = new BaseModuleBuilder();

Это не выглядит умным, но это очень смиренно, и asp.net должен сделать все для вас. В случае, если ваш список слишком динамичен, это может быть что-то вроде

var temp = Activator.CreateInstance(Type.GetType("BaseModuleBuilder, Modules.dll"));

Обязательно всегда указывайте DLL при работе с динамически загружаемыми классами.

...