Tôi đã thực hiện mô hình sau bởi jbogard:Làm cách nào để xử lý các sự kiện miền được xử lý bởi trình xử lý sự kiện?
http://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/
Hãy tưởng tượng sau đây thực thể Coupon
và sự kiện CouponActivatedEvent
:
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));
}
}
Việc xử lý sự kiện sau đây 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
}
}
}
sauoverride trên DbContext
(Entity Framework 6), lấy từ bài viết trên blog của jbogard:
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();
}
Nếu bây giờ chúng ta kích hoạt một phiếu giảm giá, điều này sẽ nâng cao CouponActivatedEvent
. Khi gọi SaveChanges
, trình xử lý sẽ được thực thi và UserReceivedCreditEvent
và CreditCreatedEvent
sẽ được nâng lên. Họ sẽ không được xử lý mặc dù. Tôi có hiểu lầm về mô hình không? Hoặc là ghi đè SaveChanges
không thích hợp?
Tôi đã cân nhắc tạo vòng lặp sẽ lặp lại cho đến khi không có sự kiện mới được nâng lên trước khi chuyển sang base.SaveChanges();
... nhưng tôi lo rằng mình sẽ vô tình tạo vòng lặp vô tận. Giống như vậy:
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();
}
Cảm ơn, bạn đã làm rõ nhiều điều cho tôi. Bạn có biết một dự án ví dụ được thiết kế theo cách bạn mô tả không? Tôi nghĩ rằng tôi có được ý tưởng, tôi chỉ không chắc chắn làm thế nào để thực hiện nó đúng cách. – Korijn
Ví dụ, không thực sự. Nhưng bắt đầu thực hiện nó, thực hành làm cho hoàn hảo. Làm, nhận thấy những gì cảm thấy cồng kềnh, cố gắng refactor vv DDD được học bằng cách làm nó. – MikeSW
Tôi nhận được nó ngay bây giờ, cụ thể là * xử lý sự kiện phản ứng với những điều đã xảy ra trong quá khứ * giải thích rất nhiều. – Korijn