Проблемы с динамической загрузкой сборочных зависимостей
Позвольте мне попытаться объяснить мою проблему. В настоящее время я пытаюсь разработать небольшой "плагин-фреймворк", написанный на.Net (в основном для экспериментов). Таким образом, идея заключается в том, чтобы иметь основное приложение, в которое можно добавить "плагины", развернув dll в определенной папке "плагины" основного приложения. Все работает нормально, плагины созданы должным образом, однако сейчас я столкнулся с проблемой. Я развернул сейчас плагин "X", который использует дополнительные сторонние плагины, и теперь у меня проблема, что эти дополнительные сторонние плагины, требуемые для "X", не найдены во время выполнения. Поэтому моя идея состоит в том, чтобы добавить дополнительный каталог "зависимости", где я также разверну все необходимые плагины.
Итак, мой первый вопрос: как я могу загрузить сборки в домен приложения (если я знаю путь к ним), если они могут использоваться моим приложением?
Я пытался приблизиться к этому, делая что-то вроде:
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//find the path to the assembly and then load and return it by
//return Assembly.Load("pathToDependencies/failedAssembly.dll");
}
Проблема заключается в том, что этот обработчик событий теперь активируется с помощью "Presentation.Zune.dll" в переменной args (я использую приложение WPF). Кажется, что эта сборка не удалось загрузить, но фактическая проблема является другой DLL.
Может кто-нибудь предложить мне лучший способ решить мою проблему? Я надеюсь, что мне удалось объяснить мою ситуацию в достаточной степени, в противном случае просто попросить дальнейших разъяснений.
Спасибо Юрий
3 ответа
Вы можете установить путь проверки среды выполнения, чтобы он мог найти сборки. Установите элемент исследования в конфигурационном файле вашего приложения.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="plugins;dependencies"/>
</assemblyBinding>
</runtime>
</configuration>
AssemblyResolve
Событие происходит, когда фреймворк пытается загрузить сборку и завершается неудачно.
Это означает, что если это дает вам Presentation.Zune.dll
в аргументах, что фреймворк не может найти эту сборку, и это ваш шанс перехватить ее и сделать что-то другое, например, загрузить ее из каталога, о котором фреймворк может не знать - например, из вашей папки plugins\dependencies...
С головы до головы, я бы попробовал что-то вроде этого:
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if( File.Exists(".\\Plugins\\"+args.Name) ) // it's a plugin
return Assembly.Load(".\\Plugins\\"+args.Name);
else if( File.Exists(".\\Plugins\\Dependencies\\"+args.Name) ) // it's a dependency OF a plugin
return Assembly.Load(".\\Plugins\\Dependencies\\"+args.Name);
else
throw new Exception();
}
Кстати: вы можете значительно ускорить загрузку сборок, если вы кэшируете сборки, которые вы уже разрешили в словаре. Если A зависит от B, C и B зависит от C, и вы загружаете A, AssemblyResolve будет вызываться дважды для C, и загрузка сборки только один раз быстрее:)
(Я не уверен, что это всегда так, что AssemblyResolve вызывается более одного раза, но я заметил это при отладке проекта один раз. И это не помешает кэшировать сборки...)