Отдельный сервис, вероятно, ваш лучший вариант.
Возможно, вы могли бы сделать это в одном сервисе. Однако этот «трюк», необходимый для самообновления службы, немного сложен для реализации.
То, что вам нужно было бы сделать, - это запустить службу как не более чем очень легкую службу оболочки Затем он может запустить отдельный изолированный домен AppDomain, и этот appDomain загрузит сборки вашей службы, инициализирует и запустит.
Позже, когда вы захотите выполнить обновление (которое может инициироваться через любое событие, которое может забрать служба, включая копирование новых сборок в папку обновления [через FileSystemWatcher], явное указание этого через сеть и т. Д.]), Оно будет необходимо активировать способ сказать внутреннему типу AppDomain об остановке, затем выгрузить AppDomain . На этом этапе он может выполнить шаги 3 и 4 выше. Затем нужно просто перезагрузить домен приложения, повторно запустить его инициализацию и т. Д.
Поскольку служба будет находиться в отдельном домене приложений, все это может происходить в одном исполняемом файле без остановки службы. Когда домен приложения выгружается, загружаемые им сборки также выгружаются.
Единственное требование, которое делает это трудным, заключается в том, что вы должны быть уверены, что не будете передавать какие-либо типы в основной AppDomain из созданного, иначе вы загрузите сборки в свой основной AppDomain. Это лишит вас возможности обновлять их во время выполнения.