public ProjectionEventListenerTests()
        {
            myEntity1Projector = Substitute.For <IEntityEventProjector>();

            myEntity2Projector = Substitute.For <IEntityEventProjector>();

            sequencer = Substitute.For <IAsyncEventSequencer <DomainAggregateEvent> >();
            sequencer.GetEventSequencing(null).ReturnsForAnyArgs(new[]
            {
                new EventSequencing()
                {
                    SequenceName        = "MyProjectionEventListener",
                    EventSequenceNumber = 1
                }
            });
            sequencer.ShouldAttemptSynchronousDispatch(null).ReturnsForAnyArgs(true);

            projectionSubSystem = Substitute.For <IProjectionSubSystem>();

            unitOfWorkFactory = Substitute.For <IUnitOfWorkFactory>();
            unitOfWork        = Substitute.For <IUnitOfWork>();
            unitOfWorkFactory.CreateUnitOfWork().Returns(unitOfWork);

            commandContextStack = new CommandContextStack();

            sut = Substitute.ForPartsOf <ProjectionEventListener>(projectionSubSystem, unitOfWorkFactory, commandContextStack);
            sut.EventSequencer.Returns(sequencer);
        }
        private async Task ProcessEventsAsync(IReadOnlyCollection <IAsyncEventQueueRecord> records, string queueName)
        {
            HashSet <IAsyncEventListener> usedListeners   = new HashSet <IAsyncEventListener>();
            List <IAsyncEventQueueRecord> processedEvents = new List <IAsyncEventQueueRecord>();

            foreach (var record in records)
            {
                Type listenerType      = typeof(IAsyncEventListener <>).MakeGenericType(record.EventMessage.Event.GetType());
                var  handleAsyncMethod = listenerType.GetMethod(nameof(IAsyncEventListener <IEvent> .HandleAsync));

                IEnumerable <IAsyncEventListener> listeners = serviceLocator.GetAll(listenerType).Cast <IAsyncEventListener>();
                foreach (IAsyncEventListener listener in listeners)
                {
                    IAsyncEventSequencer          sequencer = listener.EventSequencer;
                    IEnumerable <EventSequencing> sequences = sequencer.GetEventSequencing(record.EventMessage);
                    if (sequences.Any(x => x.SequenceName == queueName))
                    {
                        try
                        {
                            await(Task) handleAsyncMethod.Invoke(listener, new object[] { record.EventMessage, queueName });
                            usedListeners.Add(listener);
                        }
                        catch (Exception e)
                        {
                            string error = $"Failed processing of an async event {record.EventMessage.GetType().FullName} (ID: {record.EventId}) in queue '{queueName}' with listener {listener.GetType().FullName}";
                            Logger.Error(e, error);
                            throw new AsyncEventProcessingException(error, e);
                        }
                    }
                }

                processedEvents.Add(record);
            }

            foreach (IAsyncEventListener listener in usedListeners)
            {
                try
                {
                    await listener.OnFinishedEventQueueAsync(queueName);
                }
                catch (Exception e)
                {
                    string error = $"Failed to finish processing of an async event queue '{queueName}' with listener {listener.GetType().FullName}";
                    Logger.Error(e, error);
                    throw new AsyncEventProcessingException(error, e);
                }
            }

            foreach (var processedEvent in processedEvents)
            {
                await asyncEventQueueManager.DequeueEventAsync(processedEvent.Id);
            }

            await asyncEventQueueManager.CommitAsync();
        }