توزیعکننده (Dispatcher) (Strongly Typed) 🧠
حالا به چیزی نیاز داریم که فراخوانی handlerها را هماهنگ کند.
public interface IDomainEventsDispatcher
{
Task DispatchAsync(IEnumerable<IDomainEvent> domainEvents, CancellationToken cancellationToken = default);
}
internal sealed class DomainEventsDispatcher(IServiceProvider serviceProvider)
: IDomainEventsDispatcher
{
// ... (پیادهسازی پیچیده با Wrapper برای جلوگیری از reflection در زمان اجرا)
}
این توزیعکننده از یک wrapper برای حذف reflection در حین اجرای handler استفاده میکند در حالی که ایمنی نوع را حفظ میکند. این به ما مزایای عملکردی اجتناب از reflection در مسیر اصلی (اجرای handler) را میدهد. فراموش نکنید که توزیعکننده را با DI ثبت کنید.
مثال استفاده 🎯
در اینجا نحوه استفاده از توزیعکننده رویدادهای دامنه در اپلیکیشن شما آمده است:
public class UserController(...) : ControllerBase
{
[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegisterUserRequest request)
{
// کاربر را ایجاد کن
var user = await userService.CreateUserAsync(request.Email, request.Password);
// رویداد دامنه را منتشر کن
var userRegisteredEvent = new UserRegisteredDomainEvent(user.Id, user.Email);
await domainEventsDispatcher.DispatchAsync([userRegisteredEvent]);
return Ok(...);
}
}
محدودیتها و مزایا و معایب ⚠️
این پیادهسازی کاملاً درون-فرآیندی (in-process) اجرا میشود، که پیامدهای مهمی دارد:
• بازخورد فوری: اگر هر handler شکست بخورد، استثنا بلافاصله به فراخواننده برمیگردد.
• کنترل فراخواننده: کدی که رویدادها را توزیع میکند، تصمیم میگیرد چگونه با شکستها برخورد کند.
• نگرانیهای قابلیت اطمینان: اگر فرآیند پس از موفقیت برخی handlerها اما قبل از تکمیل دیگران کرش کند، بازیابی خودکار وجود ندارد.
برای عوارض جانبی حیاتی که نباید از دست بروند، الگوی Outbox 📬 را در نظر بگیرید.
جمعبندی 📝
Domain events
یک الگوی قدرتمند برای جداسازی منطق بیزینس هستند و شما برای استفاده مؤثر از آنها به یک فریمورک سنگین نیاز ندارید. پیادهسازیای که ما در اینجا ساختیم، یک پایه محکم فراهم میکند.
زیبایی ساختن راهحل خودتان این است که شما هر قطعه را درک میکنید، که دیباگ و سفارشیسازی را ساده میکند. این الگو به طور عالی در سیستمهای Domain-Driven Design و Clean Architecture که در آنها جداسازی منطق بیزینس حیاتی است، جای میگیرد.
بینش کلیدی، درک مزایا و معایب خود از پیش است، نه کشف آنها در پروداکشن. ساده شروع کنید، آنچه مهم است را اندازهگیری کنید و بر اساس نیازمندیهای واقعی تکامل پیدا کنید.
🔖 هشتگها:
#CSharp #SoftwareArchitecture #DomainDrivenDesign #DDD #DomainEvents #CleanArchitecture #CQRS