public static async Task <T?> AggregateStream <T>(
        this EventStoreClient eventStore,
        Guid id,
        CancellationToken cancellationToken,
        ulong?fromVersion = null
        ) where T : class, IProjection
    {
        var readResult = eventStore.ReadStreamAsync(
            Direction.Forwards,
            StreamNameMapper.ToStreamId <T>(id),
            fromVersion ?? StreamPosition.Start,
            cancellationToken: cancellationToken
            );

        // TODO: consider adding extension method for the aggregation and deserialisation
        var aggregate = (T)Activator.CreateInstance(typeof(T), true) !;

        await foreach (var @event in readResult)
        {
            var eventData = @event.Deserialize();

            aggregate.When(eventData !);
        }

        return(aggregate);
    }
    private async Task Store(T aggregate, CancellationToken cancellationToken)
    {
        var events = aggregate.DequeueUncommittedEvents();

        var eventsToStore = events
                            .Select(EventStoreDBSerializer.ToJsonEventData).ToArray();

        await eventStore.AppendToStreamAsync(
            StreamNameMapper.ToStreamId <T>(aggregate.Id),
            // TODO: Add proper optimistic concurrency handling
            StreamState.Any,
            eventsToStore,
            cancellationToken : cancellationToken
            );
    }