internal static void Perform <TCommand>(this IAggregateRoot aggregate, TCommand command) { var subscription = AggregateInvokersCache.GetWhenMethod(aggregate.GetType(), command.GetType()); if (subscription == null) { throw new InvalidOperationException("Aggregate can't perform command."); } if (aggregate.Status == RootStatus.New && !subscription.IsConstructor) { throw new InvalidOperationException("Attempting to apply a command to non existed aggregate."); } if (aggregate.Status != RootStatus.New && subscription.IsConstructor) { throw new InvalidOperationException("Attempting to create existed aggregate."); } if (aggregate.Status == RootStatus.Archived) { throw new InvalidOperationException("Aggregate is archived."); } subscription.Invoker(aggregate, command); if (aggregate.Changes.Count < 1) { throw new InvalidOperationException($"Command '{command.GetType().AssemblyQualifiedName}' produced no events"); } aggregate.Status = RootStatus.Alive; aggregate.Reel(aggregate.Changes); if (subscription.IsDestructor) { aggregate.Status = RootStatus.Archived; } }