2014-10-31 4 views
7

मैं jbogard द्वारा निम्नलिखित पैटर्न अपनाया है:ईवेंट हैंडलर द्वारा उठाए गए डोमेन ईवेंट को कैसे प्रबंधित करें?

http://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/

कल्पना कीजिए इकाई Coupon और घटना 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)); 
    } 
} 

निम्नलिखित ईवेंट हैंडलर 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 
     } 
    } 
} 

निम्नलिखितपर DbContext (इकाई की रूपरेखा 6), 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(); 
} 

अब हम एक कूपन सक्रिय करते हैं, इस CouponActivatedEvent बढ़ा देंगे। SaveChanges पर कॉल करते समय, हैंडलर निष्पादित किया जाएगा, और UserReceivedCreditEvent और CreditCreatedEvent उठाया जाएगा। हालांकि उन्हें संभाला नहीं जाएगा। क्या मैं पैटर्न को गलत समझ रहा हूं? या SaveChanges ओवरराइड उचित नहीं है?

मैं एक पाश है कि जब तक कोई नया घटनाओं base.SaveChanges(); पर जाने से पहले उठाए गए हैं दोहराया जाएगा बनाने पर विचार किया है ... लेकिन मुझे चिंता है कि अनंत छोरों गलती से पैदा करेगा हूँ। इस तरह:

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(); 
} 

उत्तर

12

हाँ, आपने चीजों को गलत समझा। एक डोमेन इवेंट सी # घटना की तरह नहीं है, यह डोमेन में क्या बदलता है इसके बारे में एक संदेश है। एक नियम यह है कि एक घटना ऐसा कुछ होता है जो अतीत में होता है। इस प्रकार, एक ईवेंट हैंडलर घटना को बदल नहीं सकता है (यह नहीं होना चाहिए), यह अतीत को बदलने जैसा है।

आप CouponActivatedHandler कम से कम, प्रयोक्ता इकाई एक स्रोत बना तो क्रेडिट की संख्या के साथ इसे अद्यतन, फिर इसे सहेजें मिलना चाहिए तो प्रकाशित एक घटना UserCreditsAdded। इससे भी बेहतर, हैंडलर को केवल AddCreditsToUser कमांड बनाना और भेजना चाहिए।

डोमेन घटनाक्रम पैटर्न के साथ, एक ऑपरेशन केवल कमांड की एक श्रृंखला है-> event-> command-> event आदि। ईवेंट हैंडलर आमतौर पर एक सेवा (या एक विधि है) जो केवल उस बिट की देखभाल करता है। घटना के प्रेषक को हैंडलर और इसके विपरीत के बारे में कुछ नहीं पता होगा।

अंगूठे नियम के रूप में, एक डोमेन ऑब्जेक्ट एक ईवेंट उत्पन्न करता है जब उसका राज्य बदल जाता है। एक सेवा उन घटनाओं को तब ले जाएगी, फिर उन्हें एक सेवा बस में भेज दें (एक साधारण ऐप के लिए, एक डीआई कंटेनर पर्याप्त है) जो उन्हें रुचि रखने वाले किसी भी व्यक्ति द्वारा संभाला जाएगा (इसका मतलब स्थानीय ऐप या उस बस की सदस्यता लेने वाले अन्य ऐप्स से सेवाएं)।

कभी भी भूलें कि किसी ऐप के आर्किटेक्चर करते समय डोमेन ईवेंट उच्च स्तर का पैटर्न होता है, यह ऑब्जेक्ट ईवेंट (जैसे सी # की घटनाओं) करने का एक और तरीका नहीं है।

+0

धन्यवाद, आपने मेरे लिए कई चीजों को स्पष्ट किया है। क्या आप एक उदाहरण परियोजना के बारे में जानते हैं जिस तरह से आप वर्णन करते हैं? मुझे लगता है कि मुझे यह विचार मिलता है, मैं बस इसे ठीक से कार्यान्वित करने के बारे में अनिश्चित हूं। – Korijn

+4

उदाहरण, वास्तव में नहीं। लेकिन इसे शुरू करना, अभ्यास सही बनाता है। क्या, ध्यान दें कि बोझिल क्या लगता है, रिफैक्टर आदि का प्रयास करें। डीडीडी इसे करके सीखा है। – MikeSW

+0

मुझे अब यह मिल गया है, विशेष रूप से * ईवेंट हैंडलर अतीत में हुई चीजों पर प्रतिक्रिया करते हैं * बहुत समझाया। – Korijn

संबंधित मुद्दे