Skip to content

Commit 237b5fb

Browse files
committed
Refactor to .NET Generic Host for DI and startup
Updated application to use .NET Generic Host for dependency injection and application startup, replacing the custom GameServiceContainer. Modified Program.cs to configure the host, set up logging, and initialize services with extension methods. Refactored Form1 and other forms to accept IServiceProvider for improved service management and modularity. Created ServiceCollectionExtensions for centralized service registration. Updated ILocationManager interface to include current location key for better data access. These changes enhance the application's architecture, making it cleaner and more maintainable.
1 parent e841209 commit 237b5fb

File tree

10 files changed

+326
-134
lines changed

10 files changed

+326
-134
lines changed

Program.cs

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,112 @@
1-
using WinFormsApp1.Managers;
1+
using Microsoft.Extensions.Hosting;
2+
using Microsoft.Extensions.Logging;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using WinFormsApp1.Extensions;
25
using WinFormsApp1.Interfaces;
36

47
namespace WinFormsApp1
58
{
9+
/// <summary>
10+
/// Simple class to use for logger type argument
11+
/// </summary>
12+
internal class ApplicationHost
13+
{
14+
}
15+
616
internal static class Program
717
{
818
/// <summary>
9-
/// The main entry point for the application.
19+
/// The main entry point for the application.
1020
/// </summary>
1121
[STAThread]
12-
static void Main()
22+
static void Main(string[] args)
1323
{
14-
// To customize application configuration such as set high DPI settings or default font,
15-
// see https://aka.ms/applicationconfiguration.
16-
ApplicationConfiguration.Initialize();
17-
18-
// Initialize the event-driven architecture
19-
var serviceContainer = InitializeServices();
20-
21-
// Create and run the main form with dependency injection
22-
var mainForm = new Form1(serviceContainer);
23-
Application.Run(mainForm);
24+
// Configure WinForms
25+
Application.SetHighDpiMode(HighDpiMode.SystemAware);
26+
Application.EnableVisualStyles();
27+
Application.SetCompatibleTextRenderingDefault(false);
28+
29+
// Create and configure the host builder
30+
var builder = Host.CreateApplicationBuilder(args);
31+
32+
// Configure services
33+
builder.Services.AddGameServices();
34+
builder.Services.AddGameLogging();
35+
builder.Services.AddGameConfiguration();
36+
37+
// Configure additional host settings
38+
builder.Logging.SetMinimumLevel(LogLevel.Information);
39+
40+
// Build the host
41+
using var host = builder.Build();
42+
43+
try
44+
{
45+
// Get the logger
46+
var logger = host.Services.GetRequiredService<ILogger<ApplicationHost>>();
47+
logger.LogInformation("Starting Realm of Aethermoor application");
48+
49+
// Initialize all managers
50+
InitializeManagers(host.Services, logger);
51+
52+
// Create and run the main form
53+
using var scope = host.Services.CreateScope();
54+
var mainForm = scope.ServiceProvider.GetRequiredService<Form1>();
55+
56+
logger.LogInformation("Starting WinForms application");
57+
Application.Run(mainForm);
58+
59+
logger.LogInformation("WinForms application closed");
60+
}
61+
catch (Exception ex)
62+
{
63+
// Log any unhandled exceptions
64+
var logger = host.Services.GetService<ILogger<ApplicationHost>>();
65+
logger?.LogCritical(ex, "Application terminated unexpectedly");
66+
throw;
67+
}
2468
}
2569

26-
private static GameServiceContainer InitializeServices()
70+
private static void InitializeManagers(IServiceProvider serviceProvider, ILogger logger)
2771
{
28-
var serviceContainer = new GameServiceContainer();
29-
30-
// Register core services
31-
var eventManager = new EventManager();
32-
serviceContainer.RegisterSingleton<IEventManager>(eventManager);
72+
try
73+
{
74+
logger.LogInformation("Initializing game managers...");
3375

34-
// Register managers in dependency order
35-
var playerManager = new PlayerManager(eventManager);
36-
serviceContainer.RegisterSingleton<IPlayerManager>(playerManager);
76+
// Initialize managers in dependency order
77+
var playerManager = serviceProvider.GetRequiredService<IPlayerManager>();
78+
var gameManager = serviceProvider.GetRequiredService<IGameManager>();
79+
var combatManager = serviceProvider.GetRequiredService<ICombatManager>();
80+
var inventoryManager = serviceProvider.GetRequiredService<IInventoryManager>();
81+
var locationManager = serviceProvider.GetRequiredService<ILocationManager>();
82+
var skillManager = serviceProvider.GetRequiredService<ISkillManager>();
3783

38-
var gameManager = new GameManager(eventManager, playerManager);
39-
serviceContainer.RegisterSingleton<IGameManager>(gameManager);
84+
// Initialize all managers
85+
if (playerManager is IBaseManager playerBaseManager)
86+
playerBaseManager.Initialize();
4087

41-
var combatManager = new CombatManager(eventManager, playerManager);
42-
serviceContainer.RegisterSingleton<ICombatManager>(combatManager);
88+
if (gameManager is IBaseManager gameBaseManager)
89+
gameBaseManager.Initialize();
4390

44-
var inventoryManager = new InventoryManager(eventManager, playerManager);
45-
serviceContainer.RegisterSingleton<IInventoryManager>(inventoryManager);
91+
if (combatManager is IBaseManager combatBaseManager)
92+
combatBaseManager.Initialize();
4693

47-
var locationManager = new LocationManager(eventManager, inventoryManager);
48-
serviceContainer.RegisterSingleton<ILocationManager>(locationManager);
94+
if (inventoryManager is IBaseManager inventoryBaseManager)
95+
inventoryBaseManager.Initialize();
4996

50-
var skillManager = new SkillManager(eventManager, playerManager);
51-
serviceContainer.RegisterSingleton<ISkillManager>(skillManager);
97+
if (locationManager is IBaseManager locationBaseManager)
98+
locationBaseManager.Initialize();
5299

53-
// Initialize all managers
54-
playerManager.Initialize();
55-
gameManager.Initialize();
56-
combatManager.Initialize();
57-
inventoryManager.Initialize();
58-
locationManager.Initialize();
59-
skillManager.Initialize();
100+
if (skillManager is IBaseManager skillBaseManager)
101+
skillBaseManager.Initialize();
60102

61-
return serviceContainer;
103+
logger.LogInformation("All game managers initialized successfully");
104+
}
105+
catch (Exception ex)
106+
{
107+
logger.LogError(ex, "Error initializing game managers");
108+
throw;
109+
}
62110
}
63111
}
64112
}

WinFormsApp1.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
<ImplicitUsings>enable</ImplicitUsings>
99
</PropertyGroup>
1010

11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
13+
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
14+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
15+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
16+
</ItemGroup>
17+
1118
<ItemGroup>
1219
<None Update="Assets\Data\CharacterClasses.json">
1320
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

docs/REFACTORING_PROGRESS.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,4 +527,33 @@
527527

528528
*Last Updated: December 31, 2024*
529529
*Document Version: 1.4*
530-
*Next Review Date: January 7, 2025*
530+
*Next Review Date: January 7, 2025*
531+
532+
### Dependency Injection Migration
533+
- **Status**: ✅ Complete (Migrated to .NET Generic Host)
534+
- **Files Created**:
535+
- `src/Extensions/ServiceCollectionExtensions.cs` - Service registration
536+
- Updated `Program.cs` - .NET Generic Host configuration with direct WinForms startup
537+
- **Files Removed**:
538+
- `src/Managers/GameServiceContainer.cs` - Replaced with .NET Generic Host
539+
- `src/Services/WinFormsHostedService.cs` - Removed IHostedService pattern
540+
541+
**Key Achievements**:
542+
- ✅ Migrated from custom GameServiceContainer to .NET Generic Host
543+
- ✅ Direct WinForms application startup in Program.cs (no IHostedService)
544+
- ✅ Proper service lifetime management (Singleton, Transient)
545+
- ✅ Comprehensive logging configuration with Microsoft.Extensions.Logging
546+
- ✅ Manager initialization with proper dependency order
547+
- ✅ Added Microsoft.Extensions.Hosting, Logging, and Configuration packages
548+
- ✅ Proper service registration with extension methods
549+
- ✅ All forms now use dependency injection constructors
550+
- ✅ Build successful with 0 errors, 342 warnings (nullable references)
551+
- ✅ Application starts and runs correctly
552+
553+
**Technical Implementation**:
554+
- **Service Registration**: Extension methods in ServiceCollectionExtensions
555+
- **Manager Lifecycle**: Singleton pattern for all managers with proper initialization
556+
- **Form Lifecycle**: Transient pattern for forms with dependency injection
557+
- **Logging**: Structured logging with Microsoft.Extensions.Logging
558+
- **Configuration**: Extensible configuration system ready for future enhancements
559+
- **Error Handling**: Comprehensive exception handling and logging
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Logging;
3+
using WinFormsApp1.Interfaces;
4+
using WinFormsApp1.Managers;
5+
6+
namespace WinFormsApp1.Extensions
7+
{
8+
/// <summary>
9+
/// Extension methods for configuring services in the dependency injection container
10+
/// </summary>
11+
public static class ServiceCollectionExtensions
12+
{
13+
/// <summary>
14+
/// Add all game services to the dependency injection container
15+
/// </summary>
16+
/// <param name="services">The service collection</param>
17+
/// <returns>The service collection for chaining</returns>
18+
public static IServiceCollection AddGameServices(this IServiceCollection services)
19+
{
20+
// Register core managers as singletons
21+
services.AddSingleton<IEventManager, EventManager>();
22+
services.AddSingleton<IPlayerManager, PlayerManager>();
23+
services.AddSingleton<IGameManager, GameManager>();
24+
services.AddSingleton<ICombatManager, CombatManager>();
25+
services.AddSingleton<IInventoryManager, InventoryManager>();
26+
services.AddSingleton<ILocationManager, LocationManager>();
27+
services.AddSingleton<ISkillManager, SkillManager>();
28+
29+
// Register forms as transient (new instance each time)
30+
services.AddTransient<Form1>();
31+
services.AddTransient<InventoryForm>();
32+
services.AddTransient<MapForm>();
33+
services.AddTransient<SkillTreeForm>();
34+
35+
return services;
36+
}
37+
38+
/// <summary>
39+
/// Configure logging for the application
40+
/// </summary>
41+
/// <param name="services">The service collection</param>
42+
/// <returns>The service collection for chaining</returns>
43+
public static IServiceCollection AddGameLogging(this IServiceCollection services)
44+
{
45+
services.AddLogging(builder =>
46+
{
47+
builder.AddConsole();
48+
builder.AddDebug();
49+
builder.SetMinimumLevel(LogLevel.Information);
50+
51+
// Add custom log filtering
52+
builder.AddFilter("Microsoft", LogLevel.Warning);
53+
builder.AddFilter("System", LogLevel.Warning);
54+
builder.AddFilter("WinFormsApp1", LogLevel.Information);
55+
});
56+
57+
return services;
58+
}
59+
60+
/// <summary>
61+
/// Add configuration services
62+
/// </summary>
63+
/// <param name="services">The service collection</param>
64+
/// <returns>The service collection for chaining</returns>
65+
public static IServiceCollection AddGameConfiguration(this IServiceCollection services)
66+
{
67+
// Configuration will be added by the host builder
68+
// This method is here for future configuration needs
69+
return services;
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)