Beispiel #1
0
        private static void InvokeApplyMethod(MethodInfo methodInfo, IEntityEvent @event, object entity,
                                              bool isReplaying)
        {
            try
            {
                var parametersCount = methodInfo.GetParameters().Length;

                switch (parametersCount)
                {
                case 1:
                    methodInfo.Invoke(entity, new object[] { @event });
                    break;

                case 2:
                    methodInfo.Invoke(entity, new object[] { @event, isReplaying });
                    break;

                default:
                    throw new ArgumentException("Invalid parameters count.");
                }
            }
            catch (ArgumentException ex)
            {
                throw new SilverbackException(
                          $"The apply method for the event of type {@event.GetType().Name} " +
                          $"in entity {entity.GetType().Name} has an invalid signature.", ex);
            }
        }
        private Task <EntityEventResult> HandleDepositMade(IEntityEvent <Guid> arg)
        {
            var dep = (DepositMadeEvent)arg;

            Balance += dep.Amount;

            return(Task.FromResult(EntityEventResult.Applied));
        }
        protected virtual Task <EntityEventResult> HandleAccountOverdrawn(IEntityEvent <Guid> arg)
        {
            var aoe = (AccountOverdrawnEvent)arg;

            Overdrawn = true;
            Balance  -= OverdraftPenalty;

            return(Task.FromResult(EntityEventResult.Applied));
        }
        private Task <EntityEventResult> HandleAccountCreated(IEntityEvent <Guid> ev)
        {
            var ac = (AccountCreatedEvent)ev;

            AccountHolderName = ac.AccountHolderName;
            Balance           = ac.OpeningBalance;
            Id = ac.EntityId;
            return(Task.FromResult(EntityEventResult.Applied));
        }
        public void CreateInstance_WithSomeEvents_EntityCreated()
        {
            var events           = new IEntityEvent[] { new Person.NameChangedEvent(), new Person.AgeChangedEvent() };
            var eventStoreEntity = new { };

            var entity = EntityActivator.CreateInstance <Person>(events, eventStoreEntity);

            entity.Should().NotBeNull();
            entity.Should().BeOfType <Person>();
        }
        public void CreateInstance_WithoutEvents_EntityCreated()
        {
            var events           = new IEntityEvent[0];
            var eventStoreEntity = new { };

            var entity = EntityActivator.CreateInstance <Person>(events, eventStoreEntity);

            entity.Should().NotBeNull();
            entity.Should().BeOfType <Person>();
        }
        public async Task <EntityEventResult> AddEvent <TEntityType>(IEntityEvent <Guid> ev) where TEntityType : class, IEntity <Guid>, new()
        {
            var entity = await GetEntity <TEntityType>(ev.EntityId);

            var retrieve = entity.ApplyEvent(ev);

            await _eventStore.StoreEvent(ev);

            return(await retrieve);
        }
Beispiel #8
0
 public EntityAndEvent(object callingEntity, IEntityEvent entityEvent)
 {
     CallingEntity = callingEntity ?? throw new ArgumentNullException(nameof(callingEntity));
     EntityEvent   = entityEvent ?? throw new ArgumentNullException(nameof(entityEvent));
     HasRemoveDuplicateAttribute = EntityEvent
                                   .GetType()
                                   .GetCustomAttribute <RemoveDuplicateEventsAttribute>() != null;
     HasDuringEventRunBeforeSave = EntityEvent
                                   .GetType()
                                   .GetCustomAttribute <MakeDuringEventRunBeforeSaveChangesAttribute>() != null;
 }
Beispiel #9
0
        /// <summary>
        ///     Maps the <see cref="IEntityEvent" /> to the related entity being persisted into the underlying
        ///     storage.
        /// </summary>
        /// <param name="entityEvent">
        ///     The entity event to be mapped.
        /// </param>
        /// <returns>
        ///     The entity representing the <see cref="IEntityEvent" />.
        /// </returns>
        protected virtual TEventEntity MapEventEntity(IEntityEvent entityEvent)
        {
            Check.NotNull(entityEvent, nameof(entityEvent));

            return(new TEventEntity
            {
                SerializedEvent = JsonSerializer.Serialize(entityEvent),
                ClrType = entityEvent.GetType().AssemblyQualifiedName,
                Timestamp = entityEvent.Timestamp,
                Sequence = entityEvent.Sequence
            });
        }
        public void CreateInstance_WithEventStoreEntity_PropertiesValuesCopiedToNewEntity()
        {
            var events           = new IEntityEvent[0];
            var eventStoreEntity = new { PersonId = 1234, Ssn = "123-123 CA", EntityName = "Silverback" };

            var entity = EntityActivator.CreateInstance <Person>(events, eventStoreEntity);

            entity.Should().NotBeNull();
            entity.Id.Should().Be(1234);
            entity.Ssn.Should().Be("123-123 CA");
            entity.Name.Should().Be("Silverback");
        }
        private Task <EntityEventResult> HandleCheckCashed(IEntityEvent <Guid> arg)
        {
            var cce = (CheckCashedEvent)arg;

            Balance -= cce.Amount;

            if (Balance < 0)
            {
                //we overdrafted!  we put out another event to let the system handle this
                var overdraftEvent = new AccountOverdrawnEvent(Id);
                EventPipeline.AddEvent <CheckingAccount>(overdraftEvent);
            }

            return(Task.FromResult(EntityEventResult.Applied));
        }
Beispiel #12
0
 /// <summary>
 /// This allows an entity to add an event to this class
 /// </summary>
 /// <param name="dEvent">This is the domain event you want to sent</param>
 /// <param name="eventToSend">This allows you to send the event to either BeforeSave, DuringSave or AfterSave. Default is BeforeSave List</param>
 public void AddEvent(IEntityEvent dEvent, EventToSend eventToSend = EventToSend.BeforeSave)
 {
     if (eventToSend == EventToSend.DuringSave)
     {
         _duringSaveEvents.Add(dEvent);
     }
     if (eventToSend == EventToSend.BeforeSave || eventToSend == EventToSend.BeforeAndAfterSave)
     {
         _beforeSaveEvents.Add(dEvent);
     }
     if (eventToSend == EventToSend.AfterSave || eventToSend == EventToSend.BeforeAndAfterSave)
     {
         _afterSaveChangesEvents.Add(dEvent);
     }
 }
        public Task <EntityEventResult> ApplyEvent(IEntityEvent <Guid> ev)
        {
            if (_mappings == null)
            {
                throw new InvalidOperationException("Entity cannot be used until SetPipeline has been called, and entity is unpopulated." +
                                                    "  Please use the Factory to GetEntity instead");
            }
            if (!_mappings.ContainsKey(ev.Name))
            {
                return(Task.FromResult(EntityEventResult.Ignored));
            }

            var func = _mappings[ev.Name];

            return(func(ev));
        }
Beispiel #14
0
        public Task <bool> StoreEvent(IEntityEvent <Guid> ev)
        {
            if (!_events.ContainsKey(ev.EntityId))
            {
                _events[ev.EntityId] = new List <IEntityEvent <Guid> > {
                    ev
                };
            }
            else
            {
                _events[ev.EntityId].Add(ev);
            }

            _lastEventTime = ev.Timestamp;
            return(Task.FromResult(true));
        }
Beispiel #15
0
        public static void Apply(IEntityEvent @event, object entity, bool isReplaying = false)
        {
            var methods = entity.GetType()
                          .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                          .Where(m => m.Name.ToLowerInvariant().StartsWith(ApplyMethodPrefix) &&
                                 m.GetParameters().Any() &&
                                 m.GetParameters().First().ParameterType.IsInstanceOfType(@event))
                          .ToList();

            if (!methods.Any())
            {
                throw new SilverbackException(
                          $"No method found to apply event of type {@event.GetType().Name} " +
                          $"in entity {entity.GetType().Name}.");
            }

            methods.ForEach(m => InvokeApplyMethod(m, @event, entity, isReplaying));
        }
        public void CreateInstance_WithSomeEvents_EventsApplied()
        {
            var events = new IEntityEvent[]
            {
                new Person.NameChangedEvent {
                    NewName = "Silverback"
                },
                new Person.AgeChangedEvent {
                    NewAge = 13
                }
            };
            var eventStoreEntity = new { };

            var entity = EntityActivator.CreateInstance <Person>(events, eventStoreEntity);

            entity.Name.Should().Be("Silverback");
            entity.Age.Should().Be(13);
        }
        /// <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);
        }
Beispiel #18
0
 public static string Serialize(IEntityEvent @event) => JsonConvert.SerializeObject(@event, typeof(IEntityEvent), SerializerSettings);
Beispiel #19
0
 public abstract Task <IStatusGeneric> HandleAsync(object callingEntity, IEntityEvent entityEvent, Guid uniqueKey);
 public override IStatusGeneric Handle(object callingEntity, IEntityEvent entityEvent)
 {
     return(_handler.Handle(callingEntity, (T)entityEvent));
 }
Beispiel #21
0
 public void AddEvent(IEntityEvent @event)
 {
     _events.Add(@event ?? throw new ArgumentNullException());
 }
Beispiel #22
0
 private bool canHandle(IEntityEvent populationEvent)
 {
     return(Equals(populationEvent.Subject, population));
 }
 public abstract IStatusGeneric Handle(object callingEntity, IEntityEvent entityEvent);
 public abstract void Handle(object callingEntity, IEntityEvent entityEvent);
Beispiel #25
0
 public void RemoveEvent(IEntityEvent @event)
 {
     _events.Remove(@event ?? throw new ArgumentNullException());
 }
Beispiel #26
0
 public EntityAndEvent(object callingEntity, IEntityEvent entityEvent)
 {
     CallingEntity = callingEntity;
     EntityEvent   = entityEvent;
 }
 private bool canHandle(IEntityEvent populationEvent)
 {
     return(Equals(populationEvent.Subject, BuildingBlock));
 }
 public override void Handle(object callingEntity, IEntityEvent entityEvent)
 {
     _handler.Handle(callingEntity, (T)entityEvent);
 }
Beispiel #29
0
 public override Task <IStatusGeneric> HandleAsync(object callingEntity, IEntityEvent entityEvent, Guid uniqueKey)
 {
     return(_handler.HandleAsync(callingEntity, (T)entityEvent, uniqueKey));
 }
 /// <summary>
 /// This allows you to create an exception with the callingEntity and domainEvent type names
 /// </summary>
 /// <param name="message"></param>
 /// <param name="callingEntity"></param>
 /// <param name="entityEvent"></param>
 public GenericEventRunnerException(string message, object callingEntity, IEntityEvent entityEvent)
     : base(message)
 {
     Data.Add("CallingEntityType", callingEntity.GetType().FullName);
     Data.Add("DomainEventType", entityEvent.GetType().FullName);
 }