Проблемы с динамической загрузкой сборочных зависимостей

Позвольте мне попытаться объяснить мою проблему. В настоящее время я пытаюсь разработать небольшой "плагин-фреймворк", написанный на.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 вызывается более одного раза, но я заметил это при отладке проекта один раз. И это не помешает кэшировать сборки...)

Другие вопросы по тегам