Введение
Раньше у меня все плагины жили в одном проекте. Удобно? Поначалу да. Но когда плагинов становится больше, начинается хаос: меняешь код в одном — случайно ломаешь другой, ведение гита вообще превращается в "кашу", и к тому же нельзя выключить недоделанный плагин, чтобы быстро запустить то, что уже давно работает.
Я решил это изменить. Моя цель — чтобы каждый плагин был независимым. Что это даст? А вот что:
- Независимые Git-репозитории. Удобно смотреть по Git flow, как писался/дорабатывался/менялся плагин со временем, откатывать и коммитить изменения.
- Независимое версионирование. Благодаря предыдущему преимуществу можно подключить инструмент вроде GitVersion и вести версионирование плагина (1.0.0, 1.1.0 и т.д.). Теперь каждый плагин будет иметь свою личную версию.
- Модульность. Каждый плагин становится самостоятельным проектом, которому для работы не нужны другие плагины, а только он сам и то, на что он ссылается (NuGet-пакеты и/или проект Common/Shared)
Теория. Как выглядит решение (Solution)
Давайте посмотрим на структуру стандартного решения в C#. В Solution (решении) находится наш проект (Project):
Мой подход предполагает именно такой вид плагинов. То есть, 1 плагин — 1 решение, в котором не будет ничего лишнего.
При таком подходе мы имеем возможность настроить версионирование для каждого плагина и сделать ему отдельный репозиторий на гите.
Возможно, вы спросите: разве это не усложнит работу? Ведь нужно собрать всё в одну панель, да и теперь нужно один и тот же код дублировать в каждом плагине... Спокойно, мы не будем повторяться!
Для того, чтобы все это увязать вместе, мы создадим еще одно решение-агрегатор. оно будет:
- Иметь ссылки на все наши плагины
- Собирать нашу панель с кнопками
Ведь нам ничего не мешает в этот Solution добавить несколько проектов.
И мы сделаем вот такую увязку проектов между собой.
Что происходит на этой схеме?
- MainApp — главный проект-агрегатор. Он имеет ссылки на PylonReinforcement и EditionsController, поэтому при сборке проекта MainApp будут собираться и эти плагины тоже. А также он имеет ссылку на проект Common.csproj, который является проектом-помощником, в который мы и будем выносить всякие общие классы, сервисы и методы.
- EditionsController имеет ссылку на Common.csproj, так как ему понадобился какой-то функционал, который мы вынесли в Common.
- PylonReinforcement является самостоятельным проектом и не нуждается в каких-либо ссылках.
Логику создания панели и кнопок непосредственно пишем в MainApp. Это теперь ваша точка входа.
Что дальше?
Мы разобрались, как разделить код и навести порядок. Но осталась еще одна головная боль — версии Revit.
В следующей части покажу, как настроить мультиверсионность через Directory.Build.props. Разберем способ, который позволяет собирать плагин под версии, которых даже нет на вашем компьютере.
--
А как вы организовали свое решение? Удобно ли работать в вашем формате? Остались вопросы? Пишите обо всем в комментариях!