using System; using System.Collections.Generic; namespace Jovian.EncounterSystem { /// /// Dispatches instances (authored on dialog options) to per-type /// handlers registered at composition time. Unknown event types are silently skipped. /// /// /// The resolver stores handlers keyed by concrete event . Registration wraps a /// typed delegate in a closure that casts back to the concrete type — the cast is safe because /// we only ever invoke the wrapped delegate via the dictionary lookup under the same key. /// public class EncounterResolver { private readonly Dictionary> handlers = new(); /// Register a handler for a concrete event type. Replaces any prior registration. /// The event type to handle. /// The delegate invoked with the cast event and the resolution context. public void Register(Action handler) where T : IEncounterEvent { handlers[typeof(T)] = (evt, ctx) => handler((T)evt, ctx); } /// Remove the handler registered for event type , if any. public void Unregister() where T : IEncounterEvent { handlers.Remove(typeof(T)); } /// Dispatch each event in to its registered handler, in order. /// Null events and events with no registered handler are skipped. /// The ordered event list (typically from an ). /// Per-resolution context passed to every handler. public void Resolve(IEnumerable events, EncounterContext context) { if(events == null) { return; } foreach(var evt in events) { if(evt == null) { continue; } if(handlers.TryGetValue(evt.GetType(), out var handler)) { handler(evt, context); } } } } }