Ich habe das folgende Muster von jbogard implementiert:Wie behandelt man Domain-Events, die von Event-Handlern ausgelöst werden?
http://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/
die CouponActivatedEvent
Coupon
und Ereignisse folgende Einheit Stellen Sie sich vor:
public class Coupon : DomainEntity
{
public virtual User User { get; private set; }
// ...omitted...
public void Activate(User user)
{
if (User != null)
throw new InvalidOperationException("Coupon already activated");
User = user;
Events.Add(new CouponActivatedEvent(this));
}
}
Die folgenden Ereignishandler CouponActivatedHandler
:
public class CouponActivatedHandler : IDomainEventHandler<CouponActivatedEvent>
{
public void Handle(CouponActivatedEvent e)
{
// user gets 5 credits because coupon was activated
for (int i = 0; i < 5; i++)
{
e.Coupon.User.AddCredit(); // raises UserReceivedCreditEvent and CreditCreatedEvent
}
}
}
Das folgende SaveChanges
Überschreibung auf DbContext
(Entity Framework 6), von jbogard Blog-Post genommen:
public override int SaveChanges()
{
var domainEventEntities = ChangeTracker.Entries<IDomainEntity>()
.Select(po => po.Entity)
.Where(po => po.Events.Any())
.ToArray();
foreach (var entity in domainEventEntities)
{
var events = entity.Events.ToArray();
entity.Events.Clear();
foreach (var domainEvent in events)
{
_dispatcher.Dispatch(domainEvent);
}
}
return base.SaveChanges();
}
Wenn wir jetzt einen Gutschein aktivieren, wird dies die CouponActivatedEvent
erhöhen. Beim Aufruf von SaveChanges
wird der Handler ausgeführt und UserReceivedCreditEvent
und CreditCreatedEvent
werden ausgelöst. Sie werden jedoch nicht behandelt. Verkenne ich das Muster? Oder ist die SaveChanges
Übersteuerung nicht geeignet?
Ich habe überlegt, eine Schleife zu erstellen, die wiederholt wird, bis keine neuen Ereignisse ausgelöst werden, bevor Sie zu base.SaveChanges();
weitergehen ... aber ich bin besorgt, dass ich aus Versehen Endlosschleifen erstellen werde. Wie so:
public override int SaveChanges()
{
do
{
var domainEventEntities = ChangeTracker.Entries<IDomainEntity>()
.Select(po => po.Entity)
.Where(po => po.Events.Any())
.ToArray();
foreach (var entity in domainEventEntities)
{
var events = entity.Events.ToArray();
entity.Events.Clear();
foreach (var domainEvent in events)
{
_dispatcher.Dispatch(domainEvent);
}
}
}
while (ChangeTracker.Entries<IDomainEntity>().Any(po => po.Entity.Events.Any()));
return base.SaveChanges();
}
Danke, Sie haben mehrere Dinge für mich geklärt. Kennen Sie ein Beispielprojekt, wie Sie es beschreiben? Ich denke, ich habe die Idee, ich bin mir nur unsicher, wie ich es richtig umsetzen soll. – Korijn
Beispiel, nicht wirklich. Aber fang an, Übung macht den Meister. Beachten Sie, was sich mühsam anfühlt, versuchen Sie es zu refaktorieren usw. DDD wird dadurch erlernt. – MikeSW
Ich bekomme es jetzt, speziell dass * Event-Handler auf Dinge reagieren, die in der Vergangenheit aufgetreten sind * viel erklärt. – Korijn