Проблемы с динамической загрузкой зависимостей сборки - PullRequest
4 голосов
/ 27 февраля 2009

позвольте мне попытаться объяснить мою проблему. В настоящее время я пытаюсь разработать небольшой «плагин-фреймворк», написанный на .Net (в основном для экспериментов). Таким образом, идея состоит в том, чтобы иметь основное приложение, в которое можно добавить «плагины», развернув dll в определенной папке «плагины» основного приложения. Все работает нормально, плагины созданы должным образом, однако сейчас я столкнулся с проблемой. Я развернул сейчас плагин «X», который использует дополнительные сторонние плагины, и поэтому у меня возникла проблема, заключающаяся в том, что эти дополнительные сторонние плагины, требуемые для «X», не найдены во время выполнения. Поэтому моя идея состоит в том, чтобы добавить дополнительный каталог «зависимости», где я также разверну все необходимые плагины.

Итак, мой первый вопрос: Как я могу загрузить сборки в домен приложения (учитывая, что я знаю путь к ним) s.t. они могут быть использованы моим приложением?

Я пытался приблизиться к этому, делая что-то вроде:

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.

Может кто-нибудь предложить мне лучший способ решить мою проблему? Я надеюсь, что смог объяснить ситуацию достаточно, в противном случае просто попросите дальнейших разъяснений.

Спасибо, Juri

Ответы [ 3 ]

9 голосов
/ 27 февраля 2009

Вы можете установить путь зондирования среды выполнения, чтобы он мог найти сборки. Установите элемент probeing в конфигурационном файле вашего приложения.

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="plugins;dependencies"/>
    </assemblyBinding>
  </runtime>
</configuration>
2 голосов
/ 27 февраля 2009

Событие AssemblyResolve наступает, когда платформа пытается загрузить сборку и завершается неудачей.

Это означает, что, если он дает вам Presentation.Zune.dll в аргументах, то фреймворк не может найти эту сборку, и это ваш шанс перехватить ее и сделать другие вещи, например загрузить ее из каталога, который Framework может не знать о - например, ваша папка 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();
}
1 голос
/ 15 июня 2009

Кстати: вы можете значительно ускорить загрузку сборок, если вы кэшируете сборки, которые вы уже разрешили в словаре. Если A зависит от B, C и B зависит от C, и вы загружаете A, AssemblyResolve будет вызываться дважды для C, и загрузка сборки только один раз быстрее:)

(Я не уверен, что всегда ли AssemblyResolve вызывается более одного раза, но я заметил это при отладке проекта один раз. И это не помешает кэшировать сборки ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...