public void Apply_PrivateApplyMethods_MethodsInvoked()
        {
            var entity = new TestEntity();

            EventsApplier.Apply(new TestEntity.TestEntityEvent2(), entity);

            entity.Calls.Should().Be(2);
        }
        public void Apply_NoMatchingMethod_ExceptionThrown()
        {
            var entity = new TestEntity();

            Action action = () => EventsApplier.Apply(new TestEntity.TestEntityEvent3(), entity);

            action.Should().Throw <SilverbackException>();
        }
        public void Apply_PublicApplyMethod_MethodInvoked()
        {
            var entity = new TestEntity();

            EventsApplier.Apply(new TestEntity.TestEntityEvent1(), entity);

            entity.Calls.Should().Be(1);
        }
        public void Apply_MultipleMatchingMethods_AllMethodsInvoked()
        {
            var entity = new TestEntity();

            EventsApplier.Apply(new TestEntity.TestEntityEvent2(), entity);

            entity.Calls.Should().Be(2);
        }
        public void Apply_SingleMatchingMethod_MethodInvoked()
        {
            var entity = new Person();

            EventsApplier.Apply(new Person.NameChangedEvent {
                NewName = "Silverback"
            }, entity);

            entity.Name.Should().Be("Silverback");
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="EventSourcingDomainEntity{TKey, TDomainEvent}" /> class
        ///     from the stored events.
        /// </summary>
        /// <param name="events">
        ///     The stored events to be re-applied to rebuild the entity state.
        /// </param>
        protected EventSourcingDomainEntity(IReadOnlyCollection <IEntityEvent> events)
        {
            Check.NotEmpty(events, nameof(events));

            events = events.OrderBy(e => e.Timestamp).ThenBy(e => e.Sequence).ToList().AsReadOnly();

            events.ForEach(e => EventsApplier.Apply(e, this, true));

            _storedEvents = events.ToList();

            ClearMessages();
        }
        /// <summary>
        ///     Adds the specified event and applies it to update the entity state.
        /// </summary>
        /// <param name="entityEvent">
        ///     The event to be added.
        /// </param>
        /// <returns>
        ///     The <see cref="IEntityEvent" /> that was added and applied.
        /// </returns>
        protected virtual IEntityEvent AddAndApplyEvent(IEntityEvent entityEvent)
        {
            Check.NotNull(entityEvent, nameof(entityEvent));

            EventsApplier.Apply(entityEvent, this);

            _newEvents ??= new List <IEntityEvent>();
            _newEvents.Add(entityEvent);

            if (entityEvent.Timestamp == default)
            {
                entityEvent.Timestamp = DateTime.UtcNow;
            }

            if (entityEvent.Sequence <= 0)
            {
                entityEvent.Sequence = (_storedEvents?.Count ?? 0) + _newEvents.Count;
            }

            return(entityEvent);
        }