@
Phase 1: Modul-System formalisiert (IModule + ModuleRegistry) - Core/Modules/IModule.cs: Vertrag (Key, DisplayName, Description, Version, RegisterServices, InitializeAsync, GetWorkers, CreateWindow) - Core/Modules/ModuleRegistry.cs - CongressTradingModule auf IModule umgestellt (instanzbasiert, Platzhalter-Fenster) - Program.cs iteriert ueber IModule[] + Registry; Form1 initialisiert Module ueber Registry - Testbarkeit: WorkerBase DB-Log-Seam (virtuell); CapitolTradesScraper.ParseTradesFromHtml extrahiert (offline gegen ct_raw.html testbar) - Tests: ModuleRegistry, CongressTradingModule, WorkerBase, CapitolTradesScraper -> 15/15 gruen Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> @
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
using IBKRTrader.Core.Workers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IBKRTrader.Core.Modules;
|
||||
|
||||
/// <summary>
|
||||
/// Vertrag für ein eigenständiges Trading-Modul.
|
||||
///
|
||||
/// Architektur-Regel: Der Core kennt konkrete Module NICHT. Module hängen sich
|
||||
/// ausschließlich über diesen Vertrag und den DI-Container ein
|
||||
/// (Abhängigkeit nur Modul → Core, niemals umgekehrt).
|
||||
///
|
||||
/// Lebenszyklus:
|
||||
/// 1. <see cref="RegisterServices"/> – vor dem Bauen des DI-Containers
|
||||
/// 2. <see cref="InitializeAsync"/> – beim App-Start (Migrationen etc.)
|
||||
/// 3. <see cref="GetWorkers"/> – Worker werden der WorkerEngine übergeben
|
||||
/// 4. <see cref="CreateWindow"/> – Launcher öffnet das Modul-Fenster
|
||||
/// </summary>
|
||||
public interface IModule
|
||||
{
|
||||
/// <summary>Eindeutiges Modul-Kürzel, zugleich DB-Tabellen-Präfix (z. B. "CT").</summary>
|
||||
string Key { get; }
|
||||
|
||||
/// <summary>Anzeigename im Launcher (z. B. "Congress Trading").</summary>
|
||||
string DisplayName { get; }
|
||||
|
||||
/// <summary>Kurzbeschreibung der Strategie für den Launcher.</summary>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>Modul-Version.</summary>
|
||||
string Version { get; }
|
||||
|
||||
/// <summary>Registriert alle Modul-Services im DI-Container (vor dem Build).</summary>
|
||||
void RegisterServices(IServiceCollection services);
|
||||
|
||||
/// <summary>Führt Modul-Migrationen und einmalige Initialisierung aus (beim Start).</summary>
|
||||
Task InitializeAsync(IServiceProvider provider);
|
||||
|
||||
/// <summary>Liefert die Worker/Services des Moduls für die WorkerEngine.</summary>
|
||||
IEnumerable<IWorker> GetWorkers(IServiceProvider provider);
|
||||
|
||||
/// <summary>Erzeugt das eigenständige Fenster des Moduls (vom Launcher geöffnet).</summary>
|
||||
Form CreateWindow(IServiceProvider provider);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace IBKRTrader.Core.Modules;
|
||||
|
||||
/// <summary>
|
||||
/// Zentrale Registry aller geladenen Module.
|
||||
/// Wird in Program.cs mit den Modul-Instanzen befüllt und als Singleton
|
||||
/// bereitgestellt, damit Launcher und Startup-Code über die Module iterieren
|
||||
/// können, ohne konkrete Modultypen zu kennen.
|
||||
/// </summary>
|
||||
public class ModuleRegistry
|
||||
{
|
||||
private readonly List<IModule> _modules;
|
||||
|
||||
public ModuleRegistry(IEnumerable<IModule> modules)
|
||||
=> _modules = modules?.ToList() ?? throw new ArgumentNullException(nameof(modules));
|
||||
|
||||
/// <summary>Alle registrierten Module in Registrierungsreihenfolge.</summary>
|
||||
public IReadOnlyList<IModule> Modules => _modules;
|
||||
|
||||
/// <summary>Findet ein Modul anhand seines Kürzels (case-insensitive) oder null.</summary>
|
||||
public IModule? Find(string key)
|
||||
=> _modules.FirstOrDefault(m => string.Equals(m.Key, key, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
Reference in New Issue
Block a user