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); }
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; }
/// <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)); }
/// <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)); }
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)); }
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); }
public static string Serialize(IEntityEvent @event) => JsonConvert.SerializeObject(@event, typeof(IEntityEvent), SerializerSettings);
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)); }
public void AddEvent(IEntityEvent @event) { _events.Add(@event ?? throw new ArgumentNullException()); }
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);
public void RemoveEvent(IEntityEvent @event) { _events.Remove(@event ?? throw new ArgumentNullException()); }
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); }
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); }