TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 548 subscribers
Post #164 138
الگوی CQRS به روشی که از ابتدا باید می‌بود 🚀


📢 MediatR
در حال تجاری شدن است.

جیمی بوگارد اعلام کرد که MediatR برای شرکت‌های بالاتر از یک اندازه مشخص، یک مدل لایسنس تجاری اتخاذ خواهد کرد.
برای بسیاری از تیم‌ها، این یک محرک برای ارزیابی مجدد استفاده از آن و احتمالاً جستجو برای جایگزین‌ها است.

و زمان بدی هم برای این کار نیست. MediatR تقریباً با CQRS در NET. مترادف شده است، با وجود این واقعیت که CQRS و MediatR یک چیز نیستند. اکثر پروژه‌ها از آن به عنوان یک لایه ارسال (dispatching) نازک برای کامندها و کوئری‌ها استفاده می‌کنند - یک مورد استفاده که می‌تواند با چند انتزاع (abstraction) ساده پوشش داده شود.

با حذف MediatR، شما به دست می‌آورید:


✅ کنترل کامل بر زیرساخت CQRS خود
✅ ارسال قابل پیش‌بینی و صریح به handlerها
✅ دیباگ و آنبوردینگ ساده‌تر
✅ راه‌اندازی تمیزتر DI و تست‌پذیری بهتر

📌ما پوشش خواهیم داد:

🔹 تعریف قراردادهای ICommand, IQuery و handlerها
🔹 افزودن پشتیبانی برای دکوراتورها (لاگینگ، اعتبارسنجی و غیره)
🔹 ثبت همه چیز با DI
🔹 یک مثال کامل و کاربردی در یک سناریوی دنیای واقعی

کامندها، کوئری‌ها و Handlerها 🧱

بیایید با تعریف قراردادهای پایه برای کامندها و کوئری‌ها شروع کنیم.
// ICommand.cs
public interface ICommand;
public interface ICommand<TResponse>;

// IQuery.cs
public interface IQuery<TResponse>;


این اینترفیس‌ها صرفاً به عنوان نشانگر وجود دارند. آن‌ها به ما اجازه می‌دهند منطق اپلیکیشن را حول نیت ساختار دهیم - عملیات نوشتن از طریق ICommand، عملیات خواندن از طریق IQuery.

اینترفیس‌های handler از همان مدل پیروی می‌کنند:
// ICommandHandler.cs
public interface ICommandHandler<in TCommand> where TCommand : ICommand
{
Task<Result> Handle(TCommand command, CancellationToken cancellationToken);
}
public interface ICommandHandler<in TCommand, TResponse> where TCommand : ICommand<TResponse>
{
Task<Result<TResponse>> Handle(TCommand command, CancellationToken cancellationToken);
}

// IQueryHandler.cs
public interface IQueryHandler<in TQuery, TResponse> where TQuery : IQuery<TResponse>
{
Task<Result<TResponse>> Handle(TQuery query, CancellationToken cancellationToken);
}


این‌ها تقریباً با APIهای IRequest و IRequestHandler MediatR یکسان هستند، که مهاجرت را در صورت خروج از MediatR بسیار ساده می‌کند.

مثال عملی: Command Handler 👨‍💻

برای دیدن این انتزاع‌ها در عمل، بیایید یک کامند را پیاده‌سازی کنیم که یک آیتم todo را به عنوان تکمیل شده علامت‌گذاری می‌کند.
// CompleteTodoCommand.cs
public sealed record CompleteTodoCommand(Guid TodoItemId) : ICommand;

// CompleteTodoCommandHandler.cs
internal sealed class CompleteTodoCommandHandler(...) : ICommandHandler<CompleteTodoCommand>
{
public async Task<Result> Handle(CompleteTodoCommand command, CancellationToken cancellationToken)
{
// ... (منطق بیزینس برای تکمیل کردن todo) ...
return Result.Success();
}
}


💡چند نکته مهم:


• کامند یک آبجکت مقدار تغییرناپذیر است (فقط داده، بدون رفتار).

• هندلر تمام منطق بیزینس را کپسوله می‌کند: اعتبارسنجی، تغییر وضعیت، ایجاد domain events و پایداری.

• هیچ mediator، ISender یا ارسال پنهانی وجود ندارد. handler مستقیماً از طریق انتزاع‌های سفارشی ما فراخوانی می‌شود.

دکوراتورها 🎨

برای پشتیبانی از دغدغه‌های مشترک (cross-cutting concerns) مانند لاگینگ، اعتبارسنجی و تراکنش‌ها، ما الگوی دکوراتور را در اطراف handlerهای خود اعمال می‌کنیم.

بیایید به دو مثال نگاه کنیم: یکی برای لاگینگ، یکی برای اعتبارسنجی.

دکوراتور لاگینگ: 📝

internal sealed clasa LoggingCommandHandler<TCommand, TResponse>(...)
: ICommandHandler<TCommand, TResponse>
where TCommand : ICommand<TResponse>
{
public async Task<Result<TResponse>> Handle(TCommand command, CancellationToken cancellationToken)
{
// ... (منطق لاگ کردن قبل و بعد از اجرای handler اصلی) ...
}
}

این کلاس هر ICommandHandler را می‌پیچد و لاگینگ ساختاریافته را در اطراف اجرای کامند اضافه می‌کند.
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →