public void Add(DomainEvent domainEvent) { if (_mergedStore != null) _mergedStore.Add(domainEvent); else _domainEvents.Add(domainEvent); }
public void CanReplay_CalledWhenAllPartsOfChainCannotReplay_ExpectFalseIsReturned( AggregateRoot aggregateRootOrNull, DomainEvent domainEventOrNull, ConstructWith construct) { var aggregateRoot = aggregateRootOrNull.ToObject(); var domainEvent = domainEventOrNull.ToObject(); var innerReplays = AtLeastOneReplayStubbedForCannotReplay().ToArray(); var chain = construct.WithChain(innerReplays); chain.CanReplay(aggregateRoot, domainEvent).Should().BeFalse(); }
public IAggregate CreateFrom(DomainEvent @event) { IAggregate aggregate = null; Func<IAggregate> factory; var isCreationEvent = factoryMethods.TryGetValue(@event.GetType(), out factory); if (isCreationEvent) { aggregate = factory(); aggregate.ApplyEvent(@event); } return aggregate; }
public void CanReplay_CalledWhenAnyPartOfChainCanReplay_ExpectTrueIsReturned( AggregateRoot aggregateRootOrNull, DomainEvent domainEventOrNull, ConstructWith construct) { var aggregateRoot = aggregateRootOrNull.ToObject(); var domainEvent = domainEventOrNull.ToObject(); var innerReplays = AtLeastOneReplayStubbedForCanReplay(aggregateRoot, domainEvent) .Concat(AnyNumberOfReplaysStubbedForCannotReplay()) .Shuffle() .ToArray(); var chain = construct.WithChain(innerReplays); chain.CanReplay(aggregateRoot, domainEvent).Should().BeTrue(); }
public void The_events_should_keep_types() { var id = Guid.NewGuid(); var toSave = new DomainEvent<Guid>[] { new NameChangedByDeedPoll {AggregateID = id, NewName = "Deed"}, new FixNameSpelling {AggregateID = id, NewName = "Fix"}, }; _store.CreateWriter<Guid>(StreamName).SaveEvents(toSave); var loaded = _store.CreateReader<Guid>(StreamName).LoadEvents(id); loaded.First().ShouldBeOfType<NameChangedByDeedPoll>(); loaded.Last().ShouldBeOfType<FixNameSpelling>(); }
public void Send(DomainEvent @event) { foreach (var registration in componentContext.ComponentRegistry.Registrations) { foreach (var service in registration.Services.OfType<TypedService>()) { var type = service.ServiceType; if (!type.IsInterface || !type.IsGenericType || !type.IsConstructedGenericType || type.GetGenericTypeDefinition() != typeof (IHandleDomainEvents<>)) { continue; } var method = type.GetMethod("Handle"); if (Enumerable.Any<ParameterInfo>(method.GetParameters(), x => x.ParameterType == @event.GetType())) { var handler = componentContext.ResolveComponent(registration, new List<Parameter>()); method.Invoke(handler, new[] {@event}); } } } }
public void TestEvent() { IEventHandlesRegistry eventHandlesRegistry = new UnityHandlesRegistry(container); eventHandlesRegistry.Register<DemoAddEvent, HandleDemoAdd>(); using (UnitOfWork unitwork = ServiceLocator.Current.GetInstance<UnitOfWork>()) { IRepository<Demo,Guid> demoRepository = ServiceLocator.Current.GetInstance<IRepository<Demo,Guid>>(); Demo demo = new Demo() { Name = "D" }; demoRepository.SaveOrUpdate(demo); DomainEvent<DemoAddEvent> demoAddEvent = new DomainEvent<DemoAddEvent>(eventHandlesRegistry); demoAddEvent.Raise(new DemoAddEvent(demo.Id)); unitwork.SaveChanges(); } }
private void InnerDispatch(DomainEvent @event) { var executors = _catalog.GetAllHandlerFor(@event.GetType()); foreach (var executor in executors) { try { if (_logger.IsDebugEnabled) _logger.Debug("Dispatching event " + @event.GetType() + " to the handler " + executor.DefiningType + "." + executor.Invoker.Method.Name); executor.Invoke(@event); if (_logger.IsDebugEnabled) _logger.Debug("Dispatched event " + @event.GetType() + " to the handler " + executor.DefiningType + "." + executor.Invoker.Method.Name); } catch (OutOfMemoryException) { throw; } catch (Exception ex) { _logger.Error("Error during dispatching event " + @event.GetType() + " to the handler " + executor.DefiningType + "." + executor.Invoker.Method.Name, ex); } } }
public EventDescriptor(Guid aggregateId, DomainEvent eventData, int version) { EventData = eventData; Version = version; Id = aggregateId; }
public void Apply(DomainEvent<Guid> e) { _projections.ForEach(p => p(e)); }
public void Publish(DomainEvent @event) { bus.Publish(@event); }
private void RaiseEvent(DomainEvent evt) { OnEventOccured?.Invoke(this, evt); }
public void IdCannotBeEmpty() { sut = Substitute.For<DomainEvent>(Guid.Empty); }
public void PublishMessage(DomainEvent thingToPublish) { mediator.Tell(new Publish("publishedEventsTopic", thingToPublish)); }
protected void RaiseEvent(DomainEvent @event) { _events.Add(@event); }
public void Process(DomainEvent ev) { ev.Process(); Log.Add(ev); }
protected override void When(DomainEvent domainEvent) { Handle(domainEvent as dynamic); }
public void Listen(IMediator mediator) { using (var consumer = new Consumer <string, string>(constructConfig(brokerList, true), new StringDeserializer(Encoding.UTF8), new StringDeserializer(Encoding.UTF8))) { consumer.OnPartitionEOF += (_, end) => Console.WriteLine($"Reached end of topic {end.Topic} partition {end.Partition}, next message will be at offset {end.Offset}"); consumer.OnError += (_, error) => Console.WriteLine($"Error: {error}"); consumer.OnConsumeError += (_, msg) => Console.WriteLine($"Error consuming from topic/partition/offset {msg.Topic}/{msg.Partition}/{msg.Offset}: {msg.Error}"); consumer.OnOffsetsCommitted += (_, commit) => { Console.WriteLine($"[{string.Join(", ", commit.Offsets)}]"); if (commit.Error) { Console.WriteLine($"Failed to commit offsets: {commit.Error}"); } Console.WriteLine($"Successfully committed offsets: [{string.Join(", ", commit.Offsets)}]"); }; consumer.OnPartitionsAssigned += (_, partitions) => { Console.WriteLine($"Assigned partitions: [{string.Join(", ", partitions)}], member id: {consumer.MemberId}"); consumer.Assign(partitions); }; consumer.OnPartitionsRevoked += (_, partitions) => { Console.WriteLine($"Revoked partitions: [{string.Join(", ", partitions)}]"); consumer.Unassign(); }; consumer.OnStatistics += (_, json) => Console.WriteLine($"Statistics: {json}"); consumer.Subscribe(this.topic); Console.WriteLine($"Subscribed to: [{string.Join(", ", consumer.Subscription)}]"); var cancelled = false; Console.CancelKeyPress += (_, e) => { e.Cancel = true; // prevent the process from terminating. cancelled = true; }; Console.WriteLine("Ctrl-C to exit."); while (!cancelled) { Message <string, string> msg; if (consumer.Consume(out msg, TimeSpan.FromSeconds(1))) { Console.WriteLine($"Topic: {msg.Topic} Partition: {msg.Partition} Offset: {msg.Offset} {msg.Value}"); try { Type eventType = Type.GetType(msg.Key); DomainEvent domainEvent = (DomainEvent)JsonConvert.DeserializeObject(msg.Value, eventType); mediator.Send(domainEvent).Wait(); } catch (DomainException ex) { Console.WriteLine(ex.BusinessMessage); } catch (TransactionConflictException ex) { Console.WriteLine(ex.DomainEvent.ToString()); } catch (JamboException ex) { Console.WriteLine(ex.Message); } } } } }
public void DHCPv4Leases_GetUsedAddresses() { Random random = new Random(); DHCPv4RootScope rootScope = GetRootScope(); Guid scopeId = Guid.NewGuid(); List <DomainEvent> events = new List <DomainEvent> { new DHCPv4ScopeAddedEvent(new DHCPv4ScopeCreateInstruction { Id = scopeId, }), }; Int32 leaseAmount = random.Next(30, 60); List <IPv4Address> expectedUsedAddress = new List <IPv4Address>(); for (int i = 0; i < leaseAmount; i++) { Guid leaseId = Guid.NewGuid(); IPv4Address address = random.GetIPv4Address(); events.Add(new DHCPv4LeaseCreatedEvent { ScopeId = scopeId, EntityId = leaseId, Address = address, ClientIdenfier = DHCPv4ClientIdentifier.FromHwAddress(random.NextBytes(6)).GetBytes(), }); DomainEvent eventToAdd = null; Boolean addressIsInUse = true; Double randomValue = random.NextDouble(); Double possiblities = 5.0; if (randomValue < 1 / possiblities) { eventToAdd = new DHCPv4LeaseReleasedEvent(leaseId); addressIsInUse = false; } else if (randomValue < 2 / possiblities) { eventToAdd = new DHCPv4LeaseRevokedEvent(leaseId); addressIsInUse = false; } else if (randomValue < 3 / possiblities) { eventToAdd = new DHCPv4AddressSuspendedEvent(leaseId, random.GetIPv4Address(), DateTime.UtcNow.AddHours(12)); addressIsInUse = false; } if (eventToAdd != null) { events.Add(eventToAdd); } if (addressIsInUse == true) { expectedUsedAddress.Add(address); } } rootScope.Load(events); DHCPv4Scope scope = rootScope.GetRootScopes().First(); List <IPv4Address> actualAddresses = scope.Leases.GetUsedAddresses().ToList(); Assert.Equal(expectedUsedAddress, actualAddresses); }
/// <summary> /// Applies a domain event to the current instance /// </summary> /// <param name="domainEvent">Event to apply</param> /// <param name="isNew">True if the event is new to the event stream; otherwise false</param> private void ApplyEventToSelf(DomainEvent domainEvent, bool isNew) { ApplyMethodWithCaching(this, domainEvent, isNew, CachedLocalMethods, false); }
public void AddEvent(DomainEvent @event) { _events.Add(@event); }
public TransactionConflictException(AggregateRoot aggregateRoot, DomainEvent domainEvent) { this.AggregateRoot = aggregateRoot; this.DomainEvent = domainEvent; }
public void On(DomainEvent e) { // Method intentionally left empty. }
public void Replay_CalledWhenChainIsEmpty_ExpectDomainEventCannotBeReplayedExceptionWithCorrectDomainEvent( AggregateRoot aggregateRootOrNull, DomainEvent domainEventOrNull, ConstructWith construct) { var aggregateRoot = aggregateRootOrNull.ToObject(); var domainEvent = domainEventOrNull.ToObject(); var chain = construct.WithChain(new IReplayDomainEvents<object>[0]); chain.Invoking(x => x.Replay(aggregateRoot, domainEvent)) .ShouldThrow<DomainEventCannotBeReplayedException>() .And.DomainEvent.Should().BeSameAs(domainEvent); }
public void AddEmittedEvent <TAggregateRoot>(DomainEvent <TAggregateRoot> e) where TAggregateRoot : AggregateRoot { Console.WriteLine("Emitted: {0}", e); }
public void VersionIsSetToDefault() { sut = Substitute.For<DomainEvent>(id); Assert.AreEqual(0, sut.EntityVersion); }
public void Handle(DomainEvent evt) => HandledEvents.Add(evt);
public void DispatchEvent(DomainEvent @event) { _dispatchQueue.Add(@event); }
public bool CanHandle(DomainEvent evt) => true;
public new void ApplyEvent(DomainEvent @event) { base.ApplyEvent(@event); }
public async Task Publish(DomainEvent domainEvent) { _logger.LogInformation(PublishInformationMessage, domainEvent.GetType().Name); await _mediator.Publish(GetNotificationCorrespondingToDomainEvent(domainEvent)); }
public void StoreEvent(DomainEvent newEvent) { UnsyncedEvents = UnsyncedEvents.Add(newEvent); RaiseEvent(newEvent); }
public void ApplyAndAddToUncommitedEvents(DomainEvent @event) { _uncommittedEvents.Add(@event); Apply(@event); }
/// <summary> /// Process a single <see cref="DomainEvent"/> against the implementation of <see cref="IAggregateRoot"/> provided in <paramref name="aggregateRecord"/> /// </summary> /// <param name="evt">The <see cref="DomainEvent"/> to process.</param> /// <param name="aggregateRecord">An instance of a <see cref="Type"/> that implements <see cref="IAggregateRoot"/>.</param> /// <returns>An instance of type <see cref="T"/>, which is the result of the application of the <see cref="DomainEvent"/> in <paramref name="evt"/> on the provided <paramref name="aggregateRecord"/>.</returns> protected abstract Task <T> ProcessEvent(DomainEvent evt, T aggregateRecord);
public void Rollback(string message) { DomainEvent.Raise <DomainNotification>(new DomainNotification("BussinessError", message)); _unitOfWork.Rollback(); }
public EventData Serialize(DomainEvent e) { VipEvent = e; return(EventData.FromDomainEvent(e, new byte[0])); }
public void CanReplay_CalledWhenChainIsEmpty_ExpectFalseIsReturned( AggregateRoot aggregateRootOrNull, DomainEvent domainEventOrNull, ConstructWith construct) { var aggregateRoot = aggregateRootOrNull.ToObject(); var domainEvent = domainEventOrNull.ToObject(); var chain = construct.WithChain(new IReplayDomainEvents<object>[0]); chain.CanReplay(aggregateRoot, domainEvent).Should().BeFalse(); }
public async Task <bool> CheckRSVP() { await((HomeLayout)App.Current.MainPage).SetLoading(true, "Syncing event RSVP status..."); status = ""; canEdit = false; buttonGrid.IsVisible = true; DomainEvent currentEvent = ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent(); ResetButtons(); //Debug.WriteLine(DateTime.Now); //Debug.WriteLine(DateTime.Now); ServerRSVP rsvp = await BaseFunctions.GetRSVPStatus(((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventID); if (rsvp != null) { status = rsvp.rsvpStatus; switch (rsvp.rsvpStatus) { case "Yes": yesButton.BackgroundColor = Color.FromHex("#00A651"); adminPost.Text = "Your attending status for " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName; yesButton.TextColor = Color.White; if (BaseFunctions.GetEventStatus(currentEvent) != EventStatus.Expired) { canEdit = true; } break; case "May be": maybeButton.BackgroundColor = Color.FromHex("#FFAC4E"); adminPost.Text = "Your attending status for " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName; maybeButton.TextColor = Color.White; if (BaseFunctions.GetEventStatus(currentEvent) != EventStatus.Expired) { canEdit = true; } break; case "No": noButton.BackgroundColor = Color.FromHex("#EF4300"); adminPost.Text = "Your attending status for " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName; noButton.TextColor = Color.White; if (currentEvent.s_event.eventAttendanceLimit > await BaseFunctions.RSVPCount(((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventID)) { if (BaseFunctions.GetEventStatus(currentEvent) != EventStatus.Expired) { canEdit = true; } } else { rsvpHeader.Text = "Its Full"; adminPost.Text = "Sorry " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName + " is at maximum capacity"; buttonGrid.IsVisible = false; yesButton.IsVisible = false; maybeButton.IsVisible = false; noButton.IsVisible = false; yesButton.TextColor = Color.Gray; yesButton.IsEnabled = false; maybeButton.TextColor = Color.Gray; maybeButton.IsEnabled = false; noButton.TextColor = Color.Gray; noButton.IsEnabled = false; } break; } } else { int count = await BaseFunctions.RSVPCount(((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventID); int attendance = currentEvent.s_event.eventAttendanceLimit; if (currentEvent.s_event.eventAttendanceLimit <= count) { rsvpHeader.Text = "Its Full"; adminPost.Text = "Sorry " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName + " is at maximum capacity"; buttonGrid.IsVisible = false; yesButton.IsVisible = false; maybeButton.IsVisible = false; noButton.IsVisible = false; yesButton.TextColor = Color.Gray; yesButton.IsEnabled = false; maybeButton.TextColor = Color.Gray; maybeButton.IsEnabled = false; noButton.TextColor = Color.Gray; noButton.IsEnabled = false; } else { if (BaseFunctions.GetEventStatus(currentEvent) != EventStatus.Expired) { canEdit = true; } } } if (BaseFunctions.GetEventStatus(currentEvent) == EventStatus.Expired) { rsvpHeader.Text = "Event Expired"; adminPost.Text = "Sorry " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName + " has concluded"; buttonGrid.IsVisible = false; yesButton.TextColor = Color.Gray; yesButton.IsEnabled = false; maybeButton.TextColor = Color.Gray; maybeButton.IsEnabled = false; noButton.TextColor = Color.Gray; noButton.IsEnabled = false; AddtoCalender.IsEnabled = false; } if (canEdit) { buttonGrid.IsVisible = true; SetRSVP("RSVP status", "Are you attending " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName + " ?"); switch (status) { case "Yes": SetRSVP("RSVP status", "Your attending status for " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName); break; case "May be": SetRSVP("RSVP status", "Your attending status for " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName); break; case "No": SetRSVP("RSVP status", "Your attending status for " + ((HomeLayout)App.Current.MainPage).GetCurrentDomainEvent().s_event.eventName); break; } } await((HomeLayout)App.Current.MainPage).SetLoading(false, "Syncing event RSVP status..."); return(true); }
internal override void SaveEvent(DomainEvent @event) { @event.SetEntityDetails(this); Parent.SaveEvent(@event); }
protected void ApplyChange(DomainEvent domainEvent) { ApplyChange(domainEvent, true); }
public void Project(DomainEvent<Guid> e) { _projections.Apply(e); }
public static IDomainEvent SetAnyVersionAndTimestamp(this DomainEvent e) => e .SetVersion(4) .SetTimestamp(DateTime.Now);
public void Replay_CalledWhenOnePartOfChainCanReplay_ExpectAggregateRootReturnedByMatchingChainEntryIsReturned( AggregateRoot aggregateRootOrNull, DomainEvent domainEventOrNull, ConstructWith construct) { var aggregateRoot = aggregateRootOrNull.ToObject(); var domainEvent = domainEventOrNull.ToObject(); var returnedAggregateRoot = new object(); var innerReplays = new[] {CreateReplayStubbedForCanReplay(aggregateRoot, domainEvent, returnedAggregateRoot)} .Concat(AnyNumberOfReplaysStubbedForCannotReplay()) .Shuffle() .ToArray(); var chain = construct.WithChain(innerReplays); chain.Replay(aggregateRoot, domainEvent).Should().BeSameAs(returnedAggregateRoot); }
public void Execute(DomainEvent @event) { Object executor = null; try { executor = _kernel.Resolve(ExecutorType); _invoker.Invoke(executor, new Object[] { @event }); } finally { _kernel.ReleaseComponent(executor); } }
public bool IsCreationEvent(DomainEvent @event) { return factoryMethods.ContainsKey(@event.GetType()); }
protected override void When(DomainEvent domainEvent) { }
public void Loading_events_since_only_gets_events_after_the_sequence() { var id = Guid.NewGuid(); var toSave = new DomainEvent<Guid>[] { new NameChangedByDeedPoll { AggregateID = id, Sequence = 3.AsSequence()}, new FixNameSpelling { AggregateID = id, Sequence = 4.AsSequence() }, new FixNameSpelling { AggregateID = id, Sequence = 5.AsSequence() }, new FixNameSpelling { AggregateID = id, Sequence = 6.AsSequence() }, }; _store.CreateWriter<Guid>(StreamName).SaveEvents(toSave); var loaded = _store.CreateReader<Guid>(StreamName).LoadEventsSince(id, 4.AsSequence()); loaded.Select(x => x.Sequence).ShouldBe(new[] { 5.AsSequence(), 6.AsSequence() }); }
public async Task Publish(DomainEvent domainEvent) { _logger.LogInformation("Publishing domain event. Event - {event}", domainEvent.GetType().Name); await _mediator.Publish(GetNotificationCorrespondingToDomainEvent(domainEvent)); }
public EventDescriptor(Guid id, DomainEvent eventData, int revision) { EventData = eventData; Revision = revision; Id = id; }
private INotification GetNotificationCorrespondingToDomainEvent(DomainEvent domainEvent) { return((INotification)Activator.CreateInstance( typeof(DomainEventNotification <>).MakeGenericType(domainEvent.GetType()), domainEvent)); }
public void IdIsSet() { sut = Substitute.For<DomainEvent>(id); Assert.AreEqual(id, sut.EntityId); }
internal void DispatchEvent(DomainEvent evt) { var chkpoint = evt.CheckpointToken; if (chkpoint > LastCheckpointDispatched) { if (_logger.IsDebugEnabled) { _logger.DebugFormat("Discharded event {0} commit {1} because last checkpoint dispatched for slot {2} is {3}.", evt.CommitId, evt.CheckpointToken, SlotName, _maxCheckpointDispatched); } return; } Interlocked.Increment(ref RebuildProjectionMetrics.CountOfConcurrentDispatchingCommit); //Console.WriteLine("[{0:00}] - Slot {1}", Thread.CurrentThread.ManagedThreadId, slotName); if (_logger.IsDebugEnabled) { _logger.ThreadProperties["commit"] = evt.CommitId; _logger.DebugFormat("Dispatching checkpoit {0} on tenant {1}", evt.CheckpointToken, _config.TenantId); } TenantContext.Enter(_config.TenantId); try { if (_logger.IsDebugEnabled) { _logger.ThreadProperties["evType"] = evt.GetType().Name; _logger.ThreadProperties["evMsId"] = evt.MessageId; _logger.ThreadProperties["evCheckpointToken"] = evt.CheckpointToken; } string eventName = evt.GetType().Name; foreach (var projection in _projections) { var cname = projection.GetCommonName(); if (_logger.IsDebugEnabled) { _logger.ThreadProperties["prj"] = cname; } bool handled; long ticks = 0; try { //pay attention, stopwatch consumes time. var sw = new Stopwatch(); sw.Start(); handled = projection.Handle(evt, true); sw.Stop(); ticks = sw.ElapsedTicks; MetricsHelper.IncrementProjectionCounterRebuild(cname, SlotName, eventName, ticks); } catch (Exception ex) { _logger.FatalFormat(ex, "[Slot: {3} Projection: {4}] Failed checkpoint: {0} StreamId: {1} Event Name: {2}", evt.CheckpointToken, evt.AggregateId, eventName, SlotName, cname ); throw; } _metrics.Inc(cname, eventName, ticks); if (_logger.IsDebugEnabled) { _logger.DebugFormat("[{3}] [{4}] Handled checkpoint {0}: {1} > {2}", evt.CheckpointToken, evt.AggregateId, eventName, SlotName, cname ); } if (_logger.IsDebugEnabled) { _logger.ThreadProperties["prj"] = null; } } ClearLoggerThreadPropertiesForEventDispatchLoop(); } catch (Exception ex) { _logger.ErrorFormat(ex, "Error dispathing commit id: {0}\nMessage: {1}\nError: {2}", evt.CheckpointToken, evt, ex.Message); ClearLoggerThreadPropertiesForEventDispatchLoop(); throw; } _lastCheckpointRebuilded = chkpoint; if (_logger.IsDebugEnabled) { _logger.ThreadProperties["commit"] = null; } Interlocked.Decrement(ref RebuildProjectionMetrics.CountOfConcurrentDispatchingCommit); }
public void VersionIsSetFromTwoParameterConstructor() { sut = Substitute.For<DomainEvent>(id, Version); Assert.AreEqual(Version, sut.EntityVersion); }
public DomainEvent GenericUpcast(DomainEvent domainEvent) { return(Upcast((T)domainEvent)); }
public void IdCannotBeEmptyInTwoParameterConstructor() { sut = Substitute.For<DomainEvent>(Guid.Empty, Version); }
protected void RegisterEvent(DomainEvent domainEvent) { _domainEvents ??= new HashSet <DomainEvent>(); _domainEvents.Add(domainEvent); }