83 lines
3.2 KiB
C#
83 lines
3.2 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using PLib.Desktop.Imaging;
|
|
using PLib.Desktop.Services;
|
|
using PLib.Desktop.Settings;
|
|
using PLib.Desktop.ViewModels;
|
|
using PLib.Infrastructure;
|
|
using PLib.Infrastructure.Storage;
|
|
using Serilog;
|
|
|
|
namespace PLib.Desktop;
|
|
|
|
/// <summary>
|
|
/// Composition root. Everything the application is made of is wired up here and nowhere else.
|
|
/// </summary>
|
|
internal static class AppHost
|
|
{
|
|
public static IHost Create(string[] args)
|
|
{
|
|
// The paths are needed to locate the user settings file, which is itself a
|
|
// configuration source — so they are built before the container exists and then
|
|
// handed to it as an instance.
|
|
var paths = new AppPaths();
|
|
|
|
// A desktop app is launched from arbitrary working directories, so the content root
|
|
// has to be the folder the executable lives in rather than Environment.CurrentDirectory.
|
|
var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings
|
|
{
|
|
Args = args,
|
|
ContentRootPath = AppContext.BaseDirectory,
|
|
});
|
|
|
|
builder.Configuration.AddJsonFile(
|
|
Path.Combine(paths.DataDirectory, "settings.json"),
|
|
optional: true,
|
|
reloadOnChange: true);
|
|
|
|
ConfigureLogging(builder, paths);
|
|
|
|
builder.Services.AddSingleton<IAppPaths>(paths);
|
|
|
|
builder.Services.AddOptions<AppearanceOptions>()
|
|
.Bind(builder.Configuration.GetSection(AppearanceOptions.SectionName));
|
|
|
|
builder.Services.AddOptions<PlaybackOptions>()
|
|
.Bind(builder.Configuration.GetSection(PlaybackOptions.SectionName))
|
|
.ValidateDataAnnotations();
|
|
builder.Services.AddPLibInfrastructure(builder.Configuration);
|
|
|
|
builder.Services.AddSingleton<ThumbnailCache>();
|
|
builder.Services.AddSingleton<IThumbnailLoader>(sp => sp.GetRequiredService<ThumbnailCache>());
|
|
builder.Services.AddSingleton<IAppSettingsStore, JsonAppSettingsStore>();
|
|
builder.Services.AddSingleton<IFolderPicker, StorageProviderFolderPicker>();
|
|
builder.Services.AddSingleton<ISystemShell, SystemShell>();
|
|
builder.Services.AddSingleton<IThemeService, ThemeService>();
|
|
builder.Services.AddSingleton<RemoteImageLoader>();
|
|
builder.Services.AddSingleton<MainWindowViewModel>();
|
|
|
|
// Scoped, not singleton: the settings dialog edits a working copy, so each opening
|
|
// gets its own model and a cancelled edit never leaks into the next one.
|
|
builder.Services.AddScoped<SettingsViewModel>();
|
|
|
|
return builder.Build();
|
|
}
|
|
|
|
private static void ConfigureLogging(HostApplicationBuilder builder, IAppPaths paths)
|
|
{
|
|
Log.Logger = new LoggerConfiguration()
|
|
.MinimumLevel.Information()
|
|
.WriteTo.Console()
|
|
.WriteTo.File(
|
|
Path.Combine(paths.DataDirectory, "logs", "plib-.log"),
|
|
rollingInterval: RollingInterval.Day,
|
|
retainedFileCountLimit: 7)
|
|
.CreateLogger();
|
|
|
|
builder.Logging.ClearProviders();
|
|
builder.Logging.AddSerilog(Log.Logger, dispose: true);
|
|
}
|
|
}
|