using System;
using Svrnty.CQRS.Events.Abstractions.EventStore;
using System.Collections.Generic;
using System.Linq;
namespace Svrnty.CQRS.Events.Abstractions.Models;
///
/// Wraps a command result with events to be emitted.
/// The framework automatically handles correlation ID assignment and event emission.
///
/// The type of the command result.
public sealed class CommandResultWithEvents
{
private readonly List _events = new();
///
/// The result of the command execution.
///
public TResult Result { get; }
///
/// Events to be emitted with automatic correlation ID management.
///
public IReadOnlyList Events => _events.AsReadOnly();
///
/// Correlation ID assigned by the framework.
/// Available after the command is processed.
/// This setter is public for framework use but should not be set by application code.
///
public string? CorrelationId { get; set; }
public CommandResultWithEvents(TResult result)
{
Result = result;
}
public CommandResultWithEvents(TResult result, params ICorrelatedEvent[] events)
{
Result = result;
_events.AddRange(events);
}
public CommandResultWithEvents(TResult result, IEnumerable events)
{
Result = result;
_events.AddRange(events);
}
///
/// Add an event to be emitted. The correlation ID will be automatically assigned.
///
public CommandResultWithEvents AddEvent(ICorrelatedEvent @event)
{
_events.Add(@event);
return this;
}
///
/// Add multiple events to be emitted. Correlation IDs will be automatically assigned.
///
public CommandResultWithEvents AddEvents(params ICorrelatedEvent[] events)
{
_events.AddRange(events);
return this;
}
///
/// Add multiple events to be emitted. Correlation IDs will be automatically assigned.
///
public CommandResultWithEvents AddEvents(IEnumerable events)
{
_events.AddRange(events);
return this;
}
///
/// Method used by the framework to assign correlation IDs to all events.
/// This method is public for framework use but should not be called by application code.
///
public void AssignCorrelationIds(string correlationId)
{
CorrelationId = correlationId;
foreach (var @event in _events)
{
// Use reflection to set the correlation ID
var correlationIdProperty = @event.GetType().GetProperty(nameof(ICorrelatedEvent.CorrelationId));
if (correlationIdProperty != null && correlationIdProperty.CanWrite)
{
correlationIdProperty.SetValue(@event, correlationId);
}
else if (correlationIdProperty != null && correlationIdProperty.GetSetMethod(nonPublic: true) != null)
{
// Handle init-only properties
correlationIdProperty.GetSetMethod(nonPublic: true)!.Invoke(@event, new object[] { correlationId });
}
}
}
}
///
/// Wraps events to be emitted for commands that don't return a result.
/// The framework automatically handles correlation ID assignment and event emission.
///
public sealed class CommandResultWithEvents
{
private readonly List _events = new();
///
/// Events to be emitted with automatic correlation ID management.
///
public IReadOnlyList Events => _events.AsReadOnly();
///
/// Correlation ID assigned by the framework.
/// Available after the command is processed.
/// This setter is public for framework use but should not be set by application code.
///
public string? CorrelationId { get; set; }
public CommandResultWithEvents()
{
}
public CommandResultWithEvents(params ICorrelatedEvent[] events)
{
_events.AddRange(events);
}
public CommandResultWithEvents(IEnumerable events)
{
_events.AddRange(events);
}
///
/// Add an event to be emitted. The correlation ID will be automatically assigned.
///
public CommandResultWithEvents AddEvent(ICorrelatedEvent @event)
{
_events.Add(@event);
return this;
}
///
/// Add multiple events to be emitted. Correlation IDs will be automatically assigned.
///
public CommandResultWithEvents AddEvents(params ICorrelatedEvent[] events)
{
_events.AddRange(events);
return this;
}
///
/// Add multiple events to be emitted. Correlation IDs will be automatically assigned.
///
public CommandResultWithEvents AddEvents(IEnumerable events)
{
_events.AddRange(events);
return this;
}
///
/// Method used by the framework to assign correlation IDs to all events.
/// This method is public for framework use but should not be called by application code.
///
public void AssignCorrelationIds(string correlationId)
{
CorrelationId = correlationId;
foreach (var @event in _events)
{
// Use reflection to set the correlation ID
var correlationIdProperty = @event.GetType().GetProperty(nameof(ICorrelatedEvent.CorrelationId));
if (correlationIdProperty != null && correlationIdProperty.CanWrite)
{
correlationIdProperty.SetValue(@event, correlationId);
}
else if (correlationIdProperty != null && correlationIdProperty.GetSetMethod(nonPublic: true) != null)
{
// Handle init-only properties
correlationIdProperty.GetSetMethod(nonPublic: true)!.Invoke(@event, new object[] { correlationId });
}
}
}
}