Есть несколько десктопных приложений, которые используют одни и те же UI-элементы, поэтому я решил вынести эти элементы в отдельную библиотеку:
ApplicationOne
ApplicationTwo
Lib.Controls
Однако часть компонентов в классах библиотеки нуждается в сервисах, которые инициализируются в корне приложения. Например, у меня есть сервис для печати этикеток. Поскольку только приложение знает, какой принтер будет использоваться, я создаю его в корне композиции и добавляю в DI-контейнер:
public class Program
{
[STAThread]
public static void Main()
{
// Label printers setup
var labelService = new LabelService();
labelService.AddLabelSetup(SupportedLabels.WarehouseProductLabel, new TscPrinter("TSC TTP-225", 200));
labelService.AddLabelSetup(SupportedLabels.OzonCargoLabel, new TscPrinter("TSC TE 200", 200, TrueTypeFont.Arial));
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddSingleton<MainWindow>();
services.AddSingleton(labelService);
})
.Build();
Lib.Controls.ApplicationHost.Init(host);
new App(host).Run();
}
}
Чтобы данный сервис был доступен в окружении Lib.Controls, я реализую в этой библиотеке статический класс:
public static class ApplicationHost
{
static IHost? _host;
public static void Init(IHost host)
{
_host = host;
}
internal static LabelService GetLabelService()
{
if (_host == null)
{
throw new Exception("Library Lib.Controls hasn't been initialized");
}
return _host.Services.GetRequiredService<LabelService>();
}
}
Теперь, если какому-либо компоненту потребуется напечатать этикетку, он сможет получить ее. Естественно, если библиотека была проинициализирована. То есть внутри библиотеки может быть такой код:
var labelService = ApplicationHost.GetLabelService();
IPage label = labelService.GetLabel(Print.Labels.SupportedLabels.OzonCargoLabel, placeholders);
viewModel.Page = label;
window.ShowDialog();
Является ли такая архитектура единственно возможной или у нее есть достойные альтернативы?
Пока что я вижу две проблемы:
- инициализация будет подключать библиотеки при старте приложения, т.е. никакого lazy loading.
- если библиотек несколько, каждую придется инициализировать отдельно в корне и вообще помнить о необходимости такой инициализации при создании других приложений.