Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

Как задать структуру выходного проекта?

#c_sharp #net #visual_studio_2015


По умолчанию VS при компиляции кладет все в одну директорию рядом с EXE.

Т.е и сборки и все остальное лежат в одной папке.

Как создать свою собственную структуру? 

Например, я хочу, что бы одни сборки клались в одну папку, другие в другую, а в корне
был EXE. 
    


Ответы

Ответ 1



Ну это как бы можно. Для начала, вы добавляете каталоги, в которых будут лежать ваши библиотеки, в assembly probing path. Для этого отредактируйте ваш app.config, добавьте в него следующее: (Документация.) Затем, в свойствах проекта в зависимостях укажите CopyLocal = False: Затем, в свойствах проекта-библиотеки установите Output Path в каталог, где вы хотите получить эту DLL (для каждого из ваших target platform/processor): Ну или в post-build step каждого из зависимых проектов укажите вручную копирование куда надо. Всё, должно работать. Как советует @Andrew B в комментариях, существует ещё один путь, описанный в документации: подписаться на событие AssemblyResolve, которое отправляется, если .NET не может загрузить сборку из вашего каталога. Для этого нужен код наподобие такого: AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve; где метод OnAssemblyResolve определён так: Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) { var name = args.Name.Substring(0, args.Name.IndexOf(",")); // проверка на то, есть ли загружаемая сборка среди наших статических ссылок // взята из https://support.microsoft.com/ru-ru/kb/837908 // но вам может быть и не нужна, подумайте сами if (!Assembly.GetExecutingAssembly().GetReferencedAssemblies() .Any(asmName => asmName.FullName.Substring(0, asmName.FullName.IndexOf(",")) == name)) { // это не assembly из наших ссылок return null; } var applicationDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); foreach (var subfolder in new[] { @"some\subfolder", @"another\subfolder" }) { var path = Path.Combine(applicationDir, subfolder, name + ".dll"; if (File.Exists(path)) return Assembly.LoadFrom(path); } return null; } (Не тестировал.) Достоинство этого решения — то, что список путей можно изменять динамически, если это вдруг понадобилось. Недостаток — то, что у вас некоторые сборки будут грузиться в assembly binding-контексте LoadFrom в отличие от обычной загрузки в контексте Load. Типы, загруженные в таком контексте, будут несовместимы с типами, загруженными в обычном контексте. Особенно это может «клюнуть», если у вас в разных местах лежат разные версии одной и той же сборки. [Это может привести к эффекту, когда один и тот же статический класс существует в двух экземплярах.] Будьте осторожны и готовы к неожиданностям! (Вопрос также обсуждался здесь.) Если ваши сборки приходят с ресурсами, возможно, вам нужно учесть эту модификацию. Дополнительное чтение по теме assembly binding/load context: Best Practices for Assembly Loading Suzanne Cook, LoadFile vs. LoadFrom Для автоматического копирования сборок в целевые каталоги посредством MSBuild посмотрите ответы к этому вопросу. Но в целом, я бы порекомендовал воспользоваться советом @TomTom и не заморачиваться, а оставить всё как есть. То, что файлы лежат в одном каталоге, пользователь не увидит, если вы правильным образом поместите ярлыки в системное меню при инсталляции (а вы в любом случае должны это сделать).

Комментариев нет:

Отправить комментарий