Ejemplo n.º 1
0
        private async Task <AggregateState> GetRehydratedStateAsync <TId>(TId aggregateUniqueId, Type aggregateType)
        {
            var events = await GetAllEventsByAggregateId(aggregateType, aggregateUniqueId).ToList().ConfigureAwait(false);

            var snapshot = await GetSnapshotFromAggregateId(aggregateUniqueId, aggregateType).ConfigureAwait(false);

            PropertyInfo   stateProp  = aggregateType.GetAllProperties().FirstOrDefault(p => p.PropertyType.IsSubclassOf(typeof(AggregateState)));
            FieldInfo      stateField = aggregateType.GetAllFields().FirstOrDefault(f => f.FieldType.IsSubclassOf(typeof(AggregateState)));
            Type           stateType  = stateProp?.PropertyType ?? stateField?.FieldType;
            AggregateState state      = null;

            if (stateType != null)
            {
                if (snapshot != null)
                {
                    state = snapshot.AggregateState;
                }
                else
                {
                    state = stateType.CreateInstance() as AggregateState;
                }
            }
            else
            {
                throw new InvalidOperationException("MongoDbEventStore.GetRehydratedAggregateAsync() : Cannot find property/field that manage state for aggregate" +
                                                    $" type {aggregateType.FullName}. State should be a property or a field of the aggregate");
            }
            state.ApplyRange(events);
            return(state);
        }
Ejemplo n.º 2
0
        private async Task <AggregateState> GetRehydratedAggregateStateAsync(
            object aggregateId,
            Type aggregateType,
            EventStoreDbContext externalCtx = null)
        {
            List <IDomainEvent> events = new List <IDomainEvent>();

#if NETSTANDARD2_0
            events = await
                     GetAllEventsByAggregateId(aggregateType, aggregateId)
                     .ToList().ConfigureAwait(false);
#elif NETSTANDARD2_1
            await foreach (var @event in GetAllEventsByAggregateId(aggregateType, aggregateId))
            {
                events.Add(@event);
            }
#endif
            if (externalCtx != null)
            {
                var eventsInChangeTracker = ExtractEventsFromChangeTracker(externalCtx).Select(GetRehydratedEventFromDbEvent);
                events = events.Concat(eventsInChangeTracker).OrderBy(s => s.Sequence).ToList();
            }
            Snapshot snapshot = null;
            using (var ctx = new EventStoreDbContext(_dbContextOptions, _archiveBehavior))
            {
                var hashedAggregateId = aggregateId.ToJson(true).GetHashCode();
                snapshot = await ctx.Set <Snapshot>()
                           .Where(t => t.AggregateType == aggregateType.AssemblyQualifiedName && t.HashedAggregateId == hashedAggregateId)
                           .FirstOrDefaultAsync().ConfigureAwait(false);
            }

            PropertyInfo   stateProp  = aggregateType.GetAllProperties().FirstOrDefault(p => p.PropertyType.IsSubclassOf(typeof(AggregateState)));
            FieldInfo      stateField = aggregateType.GetAllFields().FirstOrDefault(f => f.FieldType.IsSubclassOf(typeof(AggregateState)));
            Type           stateType  = stateProp?.PropertyType ?? stateField?.FieldType;
            AggregateState state      = null;
            if (stateType != null)
            {
                if (snapshot != null)
                {
                    state = snapshot.SnapshotData.FromJson(stateType) as AggregateState;
                }
                else
                {
                    state = stateType.CreateInstance() as AggregateState;
                }
            }
            else
            {
                throw new InvalidOperationException("EFEventStore.GetRehydratedAggregateAsync() : Cannot find property/field that manage state for aggregate" +
                                                    $" type {aggregateType.FullName}. State should be a property or a field of the aggregate");
            }

            state.ApplyRange(events);
            return(state);
        }