FruitBankHybridApp/FruitBankHybrid/MauiProgram.cs

99 lines
4.6 KiB
C#

using AyCode.Core.Loggers;
using AyCode.Services.SignalRs;
using FruitBank.Common.Loggers;
using FruitBank.Common.Models;
using FruitBank.Common.Services;
using FruitBankHybrid.Services;
using FruitBankHybrid.Services.Loggers;
using FruitBankHybrid.Shared.Databases;
using FruitBankHybrid.Shared.Services;
using FruitBankHybrid.Shared.Services.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
//using DevExpress.Maui;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Reflection;
namespace FruitBankHybrid
{
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder.UseMauiApp<App>()
//.UseDevExpress(useLocalization: false)
//.UseDevExpressCollectionView()
//.UseDevExpressControls()
//.UseDevExpressEditors()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
// Load embedded appsettings.json — MAUI has no automatic config file discovery,
// so the JSON is shipped as an EmbeddedResource (see FruitBankHybrid.csproj).
using (var appsettingsStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FruitBankHybrid.appsettings.json"))
{
if (appsettingsStream is not null)
{
var jsonConfig = new ConfigurationBuilder().AddJsonStream(appsettingsStream).Build();
builder.Configuration.AddConfiguration(jsonConfig);
}
}
#if DEBUG
builder.Services.AddSingleton<IAcLogWriterClientBase, BrowserConsoleLogWriter>();
#endif
builder.Services.AddSingleton<IAcLogWriterClientBase, SignaRClientLogItemWriter>();
// Logger factory — the Logger itself is a thin wrapper; writers (the real sinks)
// are DI singletons. Each call produces a fresh LoggerClient with the caller's categoryName.
// Mirrors the Microsoft ILoggerFactory / ILogger<T> pattern.
builder.Services.AddSingleton<Func<string, AcLoggerBase>>(sp => categoryName => new LoggerClient(categoryName, sp.GetServices<IAcLogWriterClientBase>().ToArray()));
// Bind SignalR options from configuration.
// Precedence: code default → appsettings.json (this line) → any later Configure<T> action.
builder.Services.Configure<AcHubConnectionOptions>(builder.Configuration.GetSection("AcHubConnection"));
builder.Services.Configure<AcBinaryHubProtocolOptions>(builder.Configuration.GetSection("AcBinaryHubProtocol"));
// Add device-specific services used by the FruitBankHybrid.Shared project
builder.Services.AddSingleton<IFormFactor, FormFactor>();
builder.Services.AddSingleton<ISecureCredentialService, MauiSecureCredentialService>();
builder.Services.AddSingleton<LoggedInModel>(sp => new LoggedInModel(sp.GetRequiredService<ISecureCredentialService>()));
// SignalR HubConnectionBuilder — transient so each consumer gets a fresh builder to Build().
// All connection and protocol configuration flows from appsettings.json via IOptions<T>;
// AddFruitBankDefaults only bridges the provided logger into SignalR's internal pipeline.
builder.Services.AddTransient<IHubConnectionBuilder>(sp =>
{
var loggerFactory = sp.GetRequiredService<Func<string, AcLoggerBase>>();
var connectionOpts = sp.GetRequiredService<IOptions<AcHubConnectionOptions>>().Value;
var logger = loggerFactory(nameof(FruitBankSignalRClient));
var hubBuilder = new HubConnectionBuilder().AddFruitBankDefaults(logger, connectionOpts);
hubBuilder.AddAcBinaryProtocol(); // IOptions<AcBinaryHubProtocolOptions> from DI
return hubBuilder;
});
builder.Services.AddSingleton<FruitBankSignalRClient>();
builder.Services.AddSingleton<DatabaseClient>();
builder.Services.AddMauiBlazorWebView();
builder.Services.AddDevExpressBlazor(configure => configure.SizeMode = DevExpress.Blazor.SizeMode.Medium);
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
}