Добавить путь к текущему домену приложения
У меня есть два совершенно разных каталога. В каталоге 1 содержится мое приложение, а в каталоге 2 - несколько сборок. Во время выполнения, когда приложение запускается, я буду загружать сборки. По умолчанию исполняющий домен AppDomain сборки обнаружит сборки в каталоге 1 (папка приложения) или GAC. Если файла нет, мы получим ошибку. Но я должен расширить каталог поиска AppDomain для поиска в каталоге 2 также. Таким образом, AppDomain будет искать в Directory 1 (локальный контейнер), затем в GAC, а затем по умолчанию при последнем поиске в Directory 2.
Я попытался: 1. Установив PrivateBinPath, но он ограничен только в ApplicationBaseDirectory. 2. По AssemblyResolve, но на него нет прямой ссылки. Код AssemblyResolve также никогда не попадет.
1 ответ
С использованием AssemblyResolve
Событие, как правило, правильный путь. Если его никогда не ударить, вероятно, слишком поздно. Например, когда CLR встречает метод, он полностью скомпилирует его, разрешив все его ссылки. Если такое разрешение не удается, оно всегда будет неудачным. Если вы связываете AssemblyResolve
событие после любой или всех сборок не удалось связать, событие никогда не будет срабатывать.
Чтобы решить эту проблему, убедитесь, что AssemblyResolve
событие связано как можно раньше. В исполняемом файле это достаточно просто (первым делом в точке входа вашего приложения или любой другой cctor
типа вы используете там). В библиотеке это может быть сложнее, лучше всего использовать инициализатор модуля, который запускается всякий раз, когда загружается модуль (большинство сборок содержит один модуль).
Поскольку инициализатор модуля не может быть установлен с помощью C# или любого другого языка.NET, о котором я знаю, вы должны прибегнуть к переплетению методов. Лично мне нравится Fody, и, как выясняется, для этой вещи есть предопределенный пакет Fody, называемый Fody Module Init.
Просто поместите где-нибудь публично в вашей библиотеке следующий код:
public static class ModuleInitializer
{
public static void Initialize()
{
// bind to the CurrentDomain.AssemblyResolve event
}
}
Fody также работает с другими языками (вы не указываете, какой вы используете), но тогда вам придется создать статический ModuleInitializer
класс от руки.
Используя этот подход, вы можете быть уверены, что AssemblyResolve
событие будет вызываться для любой сборки, которую Fusion CLR не может найти сам.