Как загрузить сборку во время выполнения перед событием AssemblyResolve?
На самом деле я попытался реализовать какие-то «статически связанные» сборки в моем решении. Поэтому я попробовал следующее:
- Добавление ссылки на мою сборку с помощью CopyLocal = false
- Добавление самого DLL-файла в мое решение с помощью «Добавить в качестве ссылки»
- Добавление самого файла DLL в мои ресурсы с помощью «Добавить ресурс» – «Добавить существующий файл»,
- Добавление некоторого типа из моей сборки в Form1 как
private MyObject temp = new MyObject();
После этих шагов я получил FileNotFoundException, как ожидалось. Итак, давайте попробуем загрузить сборку в AssemblyResolveEvent с помощью этого быстрого взлома
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => { Assembly MyAssembly = AppDomain.CurrentDomain.Load(Properties.Resources.ExternalAssembly); return MyAssembly; };
Так что это работает! Я могу загрузить свою сборку из файла ресурсов в AssemblyResolveEvent. Но это событие происходит только в том случае, если оно не может найти мою сборку нигде. Но как я могу загрузить свою сборку до того, как .Net попытается выполнить поиск в разных местах?
- Загрузка нескольких версий одной и той же сборки
- Поиск всех пространств имен в сборке с использованием Reflection (DotNET)
- Как вы прокручиваете загруженные в настоящее время сборки?
- Примеры предварительной выборки?
- Эффективное умножение матрицы 4x4 (C vs assembly)
Из-за фактов из проверки для ранее связанных сборок я думал, что можно будет заранее загрузить сборку в домен, и это будет принято.
Я попробовал это в program.cs, используя следующий метод Main ()
static void Main() { LoadMyAssemblies(); AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => LoadMyAssemblies(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } private static Assembly LoadMyAssemblies() { Assembly result = AppDomain.CurrentDomain.Load(Properties.Resources.MyStaticAssembly); return result; }
Но он все еще попадает в ResolveEventHandler. И намного лучше, если я снова загружу сборку и загляну в AppDomain.CurrentDomain.GetAssemblies (), я вижу, что моя assembly загружается дважды!
Итак, любая идея, почему моя загруженная assembly не будет учитываться при ее загрузке до события AssemblyResolve? С помощью отладчика я также вернул нуль, когда вызов пришел из AssemblyResolve, но в этом случае я получил исключение FileNotFoundException в начале.
- Как сохранить сборки ASP.NET в AppDomain в живых?
- Сколько циклов процессора требуется для каждой инструкции сборки?
- Как ссылаться на сборки .NET с помощью PowerShell
- Visual Studio 2010: ссылочные сборки Ориентация на версию с более высокой версией
- Что регистрирует сохранение в соглашении вызова ARM C?
- Возможно ли «декомпилировать» Windows .exe? Или, по крайней мере, рассмотреть Ассамблею?
- Как загрузить сборку в AppDomain со всеми ссылками рекурсивно?
- Как определить, была ли assembly .NET построена для x86 или x64?
На всякий случай, когда вы не знали, есть инструмент ILMerge из MS Research, который объединяет сборки в один файл.
Также вы можете создавать сборки с несколькими файлами, используя инструмент Assembly Linker .
Плюс, чтобы ответить на ваш оригинальный вопрос, проблема, я думаю, в том, что среда выполнения не знает, что assembly, которую вы загрузили вручную, является той, которую она должна искать. Поэтому в сборке разрешите событие вместо загрузки сборки снова, просто верните ссылку на сборку, которую вы вручную загрузили.
CLR Binder не знает, что LoadMyAssemblies () делает то же самое, что и событие AssemblyResolve, и что они оба пытаются найти одну и ту же сборку и загрузить ее.
Событие AssemblyResolve всегда запускается в тот момент, когда Binder решает, что он искал все возможные местоположения (которые доступны для поиска по этому приложению) и не смог найти совпадение.
Это требует первоначального вопроса, а именно, почему вы хотите статически связать свои управляемые сборки? Прочтите эту тему для многого обсуждения этого преимущества статической связи
Я продолжу и отвечу на вопрос о том, как избежать попадания в событие AssemblyResolve. 1) Поместите сборку в GAC. Что касается Binder, то GAC всегда выигрывает. 2) Поместите свою сборку на пробный путь и убедитесь, что Binder ее подбирает (посмотрите на статью «Как среда выполнения находит сборки» в MSDN для получения дополнительной информации об этом).