C#: каталог пользовательских сборок

Скажем, у нас есть приложение, которое состоит из одного исполняемого файла и 5 библиотек. Регулярно все они будут храниться в одном каталоге, и библиотеки будут загружаться оттуда.

Можно ли сделать так, чтобы я мог иметь, например, некоторые из библиотек в одном каталоге с именем Lib, а остальные - в одном под названием Lib2? Так что каталог приложения будет содержать только сам исполняемый файл, а другие сборки будут содержаться в различных логических каталогах.

Как я могу это сделать? И я хотел бы знать, как выполнять загрузку сборок, а также как сделать так, чтобы сборка приложения помещала сборки в правильный каталог.

4 ответа

Решение

Вы можете добавить дополнительные пути поиска в ваш app.config, в который он смотрит, чтобы загрузить сборки. Например

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <probing privatePath="lib;thirdParty" />
  </assemblyBinding>
</runtime>

Вы можете увидеть более подробную информацию здесь.

Если вы хотите вручную определить, откуда брать сборки, у вас есть две возможности:

  1. Обработайте событие AppDomain.AssemblyResolve (как описано SLaks). Вот фрагмент кода:

    static void Main(string[] args)
    {
       ...
       AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
       ...
    }
    
    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
       string assembliesDir = "your_directory";
       Assembly asm = Assembly.LoadFrom(Path.Combine(assembliesDir, args.Name + ".dll"));
       return asm;
    }
    
  2. Создайте домен со своими собственными настройками (установив свойства ApplicationBase или PrivateBinPath объекта AppDomainSetup).

Поэтому, если вы хотите продолжить работу в текущем домене, вы должны использовать метод 1.

Чтобы автоматически копировать сборки в папку, в которую вы хотите их поместить, вы можете установить Copy Local true для всех ссылок и сделайте шаг после сборки, чтобы переместить их в подкаталоги.

В качестве альтернативы, вы можете установить Copy Local в false и добавьте указанные DLL-файлы как файлы в проект в соответствующие подкаталоги, и установите Build Action Копировать в выходной каталог (это сохранит подкаталоги)

Самый гибкий способ найти их во время выполнения - это обработать событие AppDomain.AssemblyResolve и вручную загрузить сборку, используя Assembly.LoadFile. Вам нужно, чтобы ваш код знал, какие сборки находятся в каких каталогах.

В вашем комментарии вы упоминаете добавление путей и местоположений во время выполнения. Да, вы можете, но вы должны использовать Assembly.Load() и, возможно, отражение.

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