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

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

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

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

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>

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

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

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();
}