Introduce IImageCreator interface for image creation, and update ImageCreatorSharp to implement it. Add ImageCreatorAlternate (adapter) and ImageCreatorMapper (runtime selector) classes. Extend PicSettings with ImageCreatorProvider to control backend selection. Update DI registrations and refactor ImageCreationStuff to depend on IImageCreator, enabling backend switching via configuration.
171 lines
No EOL
6.4 KiB
C#
171 lines
No EOL
6.4 KiB
C#
using System.Runtime.InteropServices;
|
|
using ImageCatalog;
|
|
using ImageCatalog_2.Services;
|
|
using MaddoShared;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using AutoMapper;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Microsoft.Extensions.Logging.Console;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace ImageCatalog_2;
|
|
|
|
static class Program
|
|
{
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool AllocConsole();
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern IntPtr GetStdHandle(int nStdHandle);
|
|
|
|
private const int STD_OUTPUT_HANDLE = -11;
|
|
private const int STD_ERROR_HANDLE = -12;
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool SetStdHandle(int nStdHandle, IntPtr handle);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern IntPtr GetConsoleWindow();
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool AttachConsole(int dwProcessId);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern IntPtr CreateFile(
|
|
string lpFileName,
|
|
uint dwDesiredAccess,
|
|
uint dwShareMode,
|
|
IntPtr lpSecurityAttributes,
|
|
uint dwCreationDisposition,
|
|
uint dwFlagsAndAttributes,
|
|
IntPtr hTemplateFile);
|
|
|
|
private const uint GENERIC_WRITE = 0x40000000;
|
|
private const uint OPEN_EXISTING = 3;
|
|
|
|
private static void RedirectConsoleOutput()
|
|
{
|
|
var stdOutHandle = CreateFile("CONOUT$", GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
|
|
var safeFileHandle = new Microsoft.Win32.SafeHandles.SafeFileHandle(stdOutHandle, true);
|
|
var fileStream = new FileStream(safeFileHandle, FileAccess.Write);
|
|
var standardOutput = new StreamWriter(fileStream) { AutoFlush = true };
|
|
Console.SetOut(standardOutput);
|
|
Console.SetError(standardOutput);
|
|
}
|
|
|
|
public static IServiceProvider ServiceProvider { get; private set; }
|
|
[STAThread]
|
|
static void Main()
|
|
{
|
|
Application.SetHighDpiMode(HighDpiMode.SystemAware);
|
|
Application.EnableVisualStyles();
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
|
|
AllocConsole();
|
|
RedirectConsoleOutput();
|
|
|
|
var serviceCollection = new ServiceCollection();
|
|
ConfigureServices(serviceCollection);
|
|
|
|
ServiceProvider = serviceCollection.BuildServiceProvider();
|
|
|
|
var mainForm = ServiceProvider.GetRequiredService<MainForm>();
|
|
//var mainViewModel = ServiceProvider.GetRequiredService<DataModel>();
|
|
|
|
//mainForm.Model = mainViewModel;
|
|
|
|
Application.Run(mainForm);
|
|
}
|
|
|
|
private static void ConfigureServices(ServiceCollection services)
|
|
{
|
|
// Register AutoMapper (new AddAutoMapper overload — provide config and marker types)
|
|
services.AddAutoMapper(cfg => { }, typeof(Program));
|
|
|
|
// Register your services here
|
|
services.AddTransient<ITestService, TestService>();
|
|
services.AddTransient<ISettingsService, SettingsService>();
|
|
|
|
services.AddTransient<DataModel>(sp =>
|
|
{
|
|
// Resolve optional version provider and pass to DataModel
|
|
var testService = sp.GetRequiredService<ITestService>();
|
|
var settingsService = sp.GetRequiredService<ISettingsService>();
|
|
var imageCreation = sp.GetRequiredService<ImageCreationStuff>();
|
|
var picSettings = sp.GetRequiredService<PicSettings>();
|
|
var mapper = sp.GetRequiredService<IMapper>();
|
|
var logger = sp.GetRequiredService<ILogger<DataModel>>();
|
|
var versionProvider = sp.GetService<MaddoShared.IVersionProvider>();
|
|
|
|
return new DataModel(testService, settingsService, imageCreation, picSettings, mapper, logger, versionProvider);
|
|
});
|
|
|
|
services.AddTransient<ImageCreationStuff>();
|
|
services.AddTransient<ImageCreatorSharp>();
|
|
services.AddTransient<ImageCreatorAlternate>();
|
|
services.AddTransient<ImageCreatorMapper>();
|
|
|
|
// Register IImageCreator to be resolved via ImageCreatorMapper which selects concrete implementation at call time
|
|
services.AddTransient<IImageCreator>(sp => sp.GetRequiredService<ImageCreatorMapper>());
|
|
|
|
// Register a ParametriSetup singleton that persists user preferences in LocalApplicationData
|
|
var userPrefsPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
|
"ImageCatalog", "userprefs.xml");
|
|
services.AddSingleton(new ParametriSetup(userPrefsPath));
|
|
services.AddSingleton<PicSettings>();
|
|
|
|
// Register your forms
|
|
services.AddTransient<MainForm>();
|
|
|
|
// Version provider for UI and logging
|
|
services.AddSingleton<MaddoShared.IVersionProvider, MaddoShared.VersionProvider>();
|
|
|
|
services.AddLogging(configure =>
|
|
{
|
|
configure.AddCustomFormatter();
|
|
configure.AddConsole();
|
|
configure.SetMinimumLevel(LogLevel.Debug);
|
|
});
|
|
}
|
|
}
|
|
|
|
public static class ConsoleLoggerExtensions
|
|
{
|
|
public static ILoggingBuilder AddCustomFormatter(
|
|
this ILoggingBuilder builder) =>
|
|
builder
|
|
.AddConsole(options => options.FormatterName = nameof(CustomLoggingFormatter))
|
|
.AddConsoleFormatter<CustomLoggingFormatter, ConsoleFormatterOptions>()
|
|
.AddFilter("LuckyPennySoftware.AutoMapper.License", LogLevel.None);
|
|
}
|
|
public sealed class CustomLoggingFormatter : ConsoleFormatter, IDisposable
|
|
{
|
|
private readonly IDisposable _optionsReloadToken;
|
|
private ConsoleFormatterOptions _formatterOptions;
|
|
public CustomLoggingFormatter(IOptionsMonitor<ConsoleFormatterOptions> options)
|
|
// Case insensitive
|
|
: base(nameof(CustomLoggingFormatter)) =>
|
|
(_optionsReloadToken, _formatterOptions) =
|
|
(options.OnChange(ReloadLoggerOptions), options.CurrentValue);
|
|
private void ReloadLoggerOptions(ConsoleFormatterOptions options) =>
|
|
_formatterOptions = options;
|
|
|
|
public override void Write<TState>(
|
|
in LogEntry<TState> logEntry,
|
|
IExternalScopeProvider scopeProvider,
|
|
TextWriter textWriter)
|
|
{
|
|
string? message =
|
|
logEntry.Formatter?.Invoke(
|
|
logEntry.State, logEntry.Exception);
|
|
|
|
if (message is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
textWriter.WriteLine($"{message}");
|
|
}
|
|
public void Dispose() => _optionsReloadToken?.Dispose();
|
|
} |