การแจ้งเตือนและเหตุการณ์
เผยแพร่เหตุการณ์โดเมนด้วย MediatR
การแจ้งเตือนและเหตุการณ์ เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
คำขอกับการแจ้งเตือน
คำขอมี handler หนึ่งรายการ และส่งคืนค่า ส่วน การแจ้งเตือน เป็นการกระจายข้อความ โดยมี handler ได้ตั้งแต่ ศูนย์รายการขึ้นไป และไม่ส่งคืนค่า ใช้การแจ้งเตือนเพื่อประกาศว่ามีบางสิ่งเกิดขึ้น
// Request: one handler, returns a result
// Notification: many handlers, fire-and-forgetINotification
เหตุการณ์โดเมนคือระเบียนที่ใช้งาน INotification โดยอธิบายข้อเท็จจริงที่เกิดขึ้นแล้วในรูปอดีตกาล
public record OrderPlacedNotification(int OrderId, int CustomerId)
: INotification;INotificationHandler
สมาชิกผู้รับแต่ละรายใช้งาน INotificationHandler<TNotification> สมาชิกผู้รับหลายรายสามารถสมัครรับการแจ้งเตือนเดียวกันได้ โดยแต่ละรายจะจัดการอย่างเป็นอิสระต่อกัน
public class SendConfirmationEmailHandler
: INotificationHandler<OrderPlacedNotification>
{
public Task Handle(
OrderPlacedNotification n, CancellationToken ct)
{
// send the email...
return Task.CompletedTask;
}
}สมาชิกผู้รับหลายราย
เพิ่ม handler ได้มากเท่าที่ต้องการ handler เหล่านี้ไม่รู้จักกัน จึงสามารถเพิ่มการตอบสนองรูปแบบใหม่ได้โดยไม่ต้องแก้ไข publisher
public class UpdateInventoryHandler
: INotificationHandler<OrderPlacedNotification>
{
public Task Handle(OrderPlacedNotification n, CancellationToken ct)
{
// decrement stock...
return Task.CompletedTask;
}
}การเผยแพร่
หากต้องการส่งการแจ้งเตือน ให้ฉีด IPublisher (หรือ IMediator) แล้วเรียกใช้ Publish handler ที่ลงทะเบียนไว้ทุกตัวจะถูกเรียกใช้งาน
public class CreateOrderHandler(AppDbContext db, IPublisher publisher)
: IRequestHandler<CreateOrderCommand, int>
{
public async Task<int> Handle(CreateOrderCommand c, CancellationToken ct)
{
var order = new Order { CustomerId = c.CustomerId };
db.Orders.Add(order);
await db.SaveChangesAsync(ct);
await publisher.Publish(
new OrderPlacedNotification(order.Id, c.CustomerId), ct);
return order.Id;
}
}การแยกผลข้างเคียงออกจากกัน
การแจ้งเตือนช่วยให้กรณีใช้งานหลักมีจุดมุ่งเน้นที่ชัดเจน การวาง order จะบันทึก order และเผยแพร่เหตุการณ์เท่านั้น ส่วนการส่งอีเมลและการจัดการคลังสินค้าจะอยู่ใน handler ของตนเอง นี่คือการนำ หลักการเปิด/ปิด มาใช้งานจริง
// CreateOrderHandler does NOT know about email or inventoryกลยุทธ์การเผยแพร่
ตามค่าเริ่มต้น MediatR จะรอ handler ของการแจ้งเตือนแต่ละตัวตามลำดับ หากตัวใดตัวหนึ่งทำงานล้มเหลว handler ตัวถัดไปจะไม่ทำงาน คุณสามารถกำหนด publisher แบบกำหนดเองเพื่อให้ทำงานแบบขนานได้
builder.Services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
cfg.NotificationPublisher = new TaskWhenAllPublisher();
});การจัดการความล้มเหลว
เนื่องจาก handler ทำงานแยกจากกัน จึงควรกำหนดให้ชัดเจนว่าความล้มเหลวมีความหมายอย่างไร สำหรับผลข้างเคียงที่ไม่สำคัญ ให้ดักจับและบันทึกข้อมูลการทำงานภายใน handler เพื่อไม่ให้ความล้มเหลวหนึ่งรายการทำให้รายการอื่นหยุดทำงาน
public async Task Handle(OrderPlacedNotification n, CancellationToken ct)
{
try { await _email.SendAsync(n.CustomerId, ct); }
catch (Exception ex) { _logger.LogError(ex, "email failed"); }
}รูปแบบเหตุการณ์โดเมน
รูปแบบที่ใช้กันทั่วไปคือ ให้เอนทิตีรวบรวมเหตุการณ์โดเมน แล้วเผยแพร่เหตุการณ์ทั้งหมดหลังจากบันทึกธุรกรรม วิธีนี้รับประกันว่าเหตุการณ์จะเกิดขึ้นต่อเมื่อการเปลี่ยนแปลงถูกยืนยันแล้วเท่านั้น
await db.SaveChangesAsync(ct);
foreach (var domainEvent in order.Events)
await publisher.Publish(domainEvent, ct);
order.Events.Clear();การแจ้งเตือนกับคิวข้อความ
การแจ้งเตือนของ MediatR ทำงาน ภายในกระบวนการ และเป็นแบบซิงโครนัสภายในคำขอ สำหรับการสื่อสารข้ามบริการหรือการส่งมอบที่ต้องคงอยู่ ให้เผยแพร่ไปยังตัวกลางรับส่งข้อความจริง เช่น RabbitMQ หรือ Azure Service Bus แทน
// In-process reactions -> MediatR notifications
// Cross-service / durable -> message brokerการทดสอบการแจ้งเตือน
คุณสามารถตรวจยืนยันว่า handler เผยแพร่เหตุการณ์ที่ถูกต้อง โดยส่ง IPublisher จำลองเข้าไป แล้วตรวจสอบว่ามีการเรียกใช้งาน
var publisher = new Mock<IPublisher>();
var handler = new CreateOrderHandler(db, publisher.Object);
await handler.Handle(new CreateOrderCommand(1, []), default);
publisher.Verify(p => p.Publish(
It.IsAny<OrderPlacedNotification>(), default), Times.Once);ตรวจสอบความเข้าใจ
ยืนยันความเข้าใจเกี่ยวกับรูปแบบการแจ้งเตือน
สรุปทบทวน
คุณได้เรียนรู้เกี่ยวกับการแจ้งเตือนและเหตุการณ์ดังนี้:
INotificationคือการกระจายข้อความที่มีINotificationHandlerได้ตั้งแต่ศูนย์รายการขึ้นไป- เผยแพร่ด้วย
IPublisher.Publishเพื่อเรียกใช้งานสมาชิกผู้รับทั้งหมด - การแจ้งเตือนช่วยแยกผลข้างเคียงออกจากกัน และเป็นไปตามหลักการเปิด/ปิด
- การแจ้งเตือนทำงานภายในกระบวนการ หากต้องการเหตุการณ์ข้ามบริการหรือเหตุการณ์ที่ต้องคงอยู่ ให้ใช้ตัวกลางรับส่งข้อความ
หลักสูตร CQRS และ MediatR จบลงเพียงเท่านี้
คำถามที่พบบ่อย
บทเรียน “การแจ้งเตือนและเหตุการณ์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแจ้งเตือนและเหตุการณ์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การแจ้งเตือนและเหตุการณ์”
เผยแพร่เหตุการณ์โดเมนด้วย MediatR คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การแจ้งเตือนและเหตุการณ์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม
ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- แนวคิด CQRS
- คำสั่งและตัวจัดการด้วย MediatR
- พฤติกรรมของไปป์ไลน์
- การแจ้งเตือนและเหตุการณ์