Skip to content

Commit 9306038

Browse files
authored
Added aggragate id in domain event context (#99)
1 parent 644e715 commit 9306038

21 files changed

Lines changed: 292 additions & 90 deletions

source/EasyWay.EntityFrameworkCore/Extnsions.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using EasyWay.Internals.AggregateRoots;
2-
using EasyWay.Internals.DomainEvents;
1+
using EasyWay.Internals.DomainEvents;
2+
using EasyWay.Internals.Entities;
33
using EasyWay.Internals.Repositories;
44
using EasyWay.Internals.Transactions;
55
using Microsoft.EntityFrameworkCore;
@@ -18,8 +18,7 @@ public static void AddEntityFrameworkCore<TContext>(
1818

1919
services.AddScoped((Func<IServiceProvider, DbContext>)(sp => sp.GetRequiredService<TContext>()));
2020

21-
services.AddScoped<IAggregateRootsContext, EntityFrameworkAggregateRootsContext>();
22-
services.AddTransient<IDomainEventsContext, DomainEventsAccessor>();
21+
services.AddScoped<IEntitiesContext, EntityFrameworkEntitiesContext>();
2322

2423
services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
2524

source/EasyWay.EntityFrameworkCore/Internals/AggregateRoots/EntityFrameworkAggregateRootsContext.cs

Lines changed: 0 additions & 25 deletions
This file was deleted.

source/EasyWay.EntityFrameworkCore/Internals/DomainEvents/DomainEventsAccessor.cs

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using EasyWay.Internals.DomainEvents;
2+
using Microsoft.EntityFrameworkCore;
3+
4+
namespace EasyWay.Internals.Entities
5+
{
6+
internal sealed class EntityFrameworkEntitiesContext : IEntitiesContext
7+
{
8+
private readonly DbContext _dbContext;
9+
10+
public EntityFrameworkEntitiesContext(DbContext dbContext) => _dbContext = dbContext;
11+
12+
public IEnumerable<AggregateRoot> GetAggregateRoots() => _dbContext.ChangeTracker.Entries<AggregateRoot>().Select(x => x.Entity);
13+
14+
public IEnumerable<Entity> GetEntities() => _dbContext.ChangeTracker.Entries<Entity>().Select(x => x.Entity);
15+
}
16+
}

source/EasyWay/Entity.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ protected void Add<TDomainEvent>(TDomainEvent domainEvent)
3737
var domainEventContext = new DomainEventContext()
3838
{
3939
EventId = GuidGenerator.New,
40-
AggragetRootId = Id, // TODO what when we have object graph
41-
EntityId = Id,
40+
Entity = this,
4241
OccurrenceOnUtc = InternalClock.UtcNow,
4342
DomainEvent = domainEvent,
4443
};

source/EasyWay/Internals/AggregateRoots/ConcurrencyTokenUpdater.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
namespace EasyWay.Internals.AggregateRoots
1+
using EasyWay.Internals.DomainEvents;
2+
3+
namespace EasyWay.Internals.AggregateRoots
24
{
35
internal sealed class ConcurrencyTokenUpdater
46
{
5-
private readonly IAggregateRootsContext _aggragateRootsContext;
7+
private readonly IEntitiesContext _context;
68

7-
public ConcurrencyTokenUpdater(
8-
IAggregateRootsContext aggragateRootsContext)
9+
public ConcurrencyTokenUpdater(IEntitiesContext context)
910
{
10-
_aggragateRootsContext = aggragateRootsContext;
11+
_context = context;
1112
}
1213

1314
public void Update()
1415
{
15-
var aggragateRoots = _aggragateRootsContext.GetAggregateRoots();
16+
var aggragateRoots = _context.GetAggregateRoots();
1617

1718
foreach (var aggragateRoot in aggragateRoots)
1819
{

source/EasyWay/Internals/AggregateRoots/IAggregateRootsContext.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.Collections.ObjectModel;
2+
using System.Reflection;
3+
4+
namespace EasyWay.Internals.Assemblies
5+
{
6+
internal sealed class EntitiesFieldsInfo
7+
{
8+
internal static ReadOnlyDictionary<Type, FieldInfo[]> Dictionary;
9+
10+
internal EntitiesFieldsInfo(IEnumerable<Type> types)
11+
{
12+
var dictionary = new Dictionary<Type, FieldInfo[]>();
13+
14+
var aggregateRootTypes = types.Where(x => x.IsSubclassOf(typeof(AggregateRoot)));
15+
16+
foreach (var aggregateRootType in aggregateRootTypes)
17+
{
18+
var fields = aggregateRootType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
19+
20+
dictionary.Add(aggregateRootType, fields);
21+
}
22+
23+
Dictionary = new ReadOnlyDictionary<Type, FieldInfo[]>(dictionary);
24+
}
25+
}
26+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using System.Reflection;
3+
4+
namespace EasyWay.Internals.Assemblies
5+
{
6+
internal static class Extensions
7+
{
8+
internal static IServiceCollection AddAssemblies(
9+
this IServiceCollection services,
10+
IEnumerable<Assembly> assemblies)
11+
{
12+
var types = assemblies.SelectMany(x => x.GetTypes()).Distinct();
13+
14+
new EntitiesFieldsInfo(types);
15+
16+
return services;
17+
}
18+
}
19+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using EasyWay.Internals.Assemblies;
2+
using System.Collections;
3+
using System.Reflection;
4+
5+
namespace EasyWay.Internals.DomainEvents.AggragateRootIds
6+
{
7+
internal sealed class AggrageteRootIdSearcher
8+
{
9+
private readonly IEntitiesContext _context;
10+
11+
private readonly RelationshipsBetweenEntityAndAggragaeRoot _relation;
12+
13+
public AggrageteRootIdSearcher(
14+
IEntitiesContext context,
15+
RelationshipsBetweenEntityAndAggragaeRoot relation)
16+
{
17+
_context = context;
18+
_relation = relation;
19+
}
20+
21+
public Guid SearchId(Entity entity)
22+
{
23+
if (entity.GetType().IsSubclassOf(typeof(AggregateRoot)))
24+
{
25+
return entity.Id;
26+
}
27+
28+
var aggrageteRoots = _context.GetAggregateRoots();
29+
30+
if (aggrageteRoots.Count() == 1)
31+
{
32+
return aggrageteRoots.Single().Id;
33+
}
34+
35+
var aggragateRootType = _relation[entity.GetType()];
36+
37+
var aggragateRoots = _context.GetAggregateRoots().Where(x => x.GetType() == aggragateRootType);
38+
39+
foreach (var aggregateRoot in aggragateRoots)
40+
{
41+
var id = SearchInAggragates(entity, aggregateRoot);
42+
43+
if (id is not null)
44+
{
45+
return id.Value;
46+
}
47+
}
48+
49+
throw new NotFoundAggragateIdForDomainEvent();
50+
}
51+
52+
private static Guid? SearchInAggragates(Entity entity, AggregateRoot aggregateRoot)
53+
{
54+
var fields = EntitiesFieldsInfo.Dictionary[aggregateRoot.GetType()];
55+
56+
foreach (var field in fields)
57+
{
58+
var isEntity = field.FieldType.IsSubclassOf(typeof(Entity));
59+
60+
if (isEntity)
61+
{
62+
var isEqual = field.GetValue(aggregateRoot).Equals(entity);
63+
64+
if (isEqual)
65+
{
66+
return aggregateRoot.Id;
67+
}
68+
}
69+
70+
if (field.FieldType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(field.FieldType))
71+
{
72+
if (field.GetValue(aggregateRoot) is IEnumerable enumerable)
73+
{
74+
foreach (var en in enumerable)
75+
{
76+
if (en is Entity entityItem)
77+
{
78+
if (entityItem == entity)
79+
{
80+
return aggregateRoot.Id;
81+
}
82+
83+
}
84+
}
85+
}
86+
}
87+
}
88+
return null;
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)