Giriş

Farklı nesneler arasındaki iletişim doğrudan bağlantılar yerine merkezi bir “arabacı” (mediator) üzerinden gerçekleştiğinde, Mediator Pattern sayesinde kodunuz loosely coupled, test edilebilir ve ölçeklenebilir olur.
MediatR kütüphanesi, .NET dünyasında bu deseni en kolay uygulamanızı sağlayan popüler bir araçtır.

Bu yazıda:

  1. Mediator Pattern nedir?

  2. MediatR ile kurulum ve temel kullanım

  3. Katmanlı mimaride MediatR entegrasyonu

  4. CQRS ile birlikte MediatR senaryosu

  5. Performans ve test ipuçları

mediator-pattern-uml-diyagrami
mediator-pattern-uml-diyagrami

1. Mediator Pattern Temel Kavramları

  • Mediator (Aracı): Nesneler arasındaki tüm iletişimi kontrol eder.

  • Colleague (Katılımcı): Mediatör aracılığıyla haberleşen sınıflar.

  • Avantaj: Direct dependency’leri ortadan kaldırır.

  • Dezavantaj: Kompleks akışlar için mediator çok büyüyebilir.


2. MediatR ile Kurulum ve Temel Kullanım

A. NuGet Paketi

dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

B. Program.cs Entegrasyonu

builder.Services.AddMediatR(cfg => 
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

C. Request & Handler Tanımı

// 1. Request
public record GetProductByIdQuery(int Id) : IRequest<ProductDto>;

// 2. Handler
public class GetProductByIdHandler 
    : IRequestHandler<GetProductByIdQuery, ProductDto>
{
    private readonly IProductRepository _repo;
    private readonly IMapper _mapper;

    public GetProductByIdHandler(IProductRepository repo, IMapper mapper)
    {
        _repo = repo;
        _mapper = mapper;
    }

    public async Task<ProductDto> Handle(
        GetProductByIdQuery request, CancellationToken token)
    {
        var entity = await _repo.GetByIdAsync(request.Id);
        return _mapper.Map<ProductDto>(entity);
    }
}

D. Dispatch

public class ProductController : ControllerBase
{
    private readonly IMediator _mediator;
    public ProductController(IMediator mediator) => _mediator = mediator;

    [HttpGet("{id}")]
    public async Task<IActionResult> Get(int id)
    {
        var dto = await _mediator.Send(new GetProductByIdQuery(id));
        return Ok(dto);
    }
}

3. Katmanlı Mimari Entegrasyonu

Katman Sorumluluk
Domain / Application GetProductByIdQuery, Handler sınıfları
Infrastructure IProductRepository implementasyonları
API ProductController ve IMediator çağrısı
mediator-katmanli-mimari-semasi
mediator-katmanli-mimari-semasi

4. CQRS ile Birlikte Kullanım

MediatR, Command ve Query ayrımını (CQRS) doğal olarak destekler:

// Command
public record CreateProductCommand(string Name, decimal Price) : IRequest<int>;

// Query
public record GetAllProductsQuery() : IRequest<List<ProductDto>>;
  • Command Handler: IRequestHandler<CreateProductCommand, int>

  • Query Handler: IRequestHandler<GetAllProductsQuery, List<ProductDto>>

Bu sayede yazma ve okuma işlemlerini net şekilde ayırabilirsiniz.


5. Performans & Test İpuçları

1.Pipeline Behaviors: Önce validation, sonra logging ekleyin.

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));

2.Caching Behavior: Sık kullanılan sorgular için ara katman oluşturun.

3.Unit Test: Handler’ları doğrudan test edin, gerçek MediatR’a ihtiyaç kalmaz.

4.Profiling: MiniProfiler veya BenchmarkDotNet ile Send() çağrısını ölçün.


Dahili Bağlantılar

  • Result Pattern ile tutarlı dönüşler için bu yazıya bakın.

  • Dependency Injection detayları için buraya göz atın.


İleri Okuma ve Kaynaklar


6. Sonuç

  • Mediator Pattern, katılımcılar arasındaki bağımlılığı ortadan kaldırır.

  • MediatR kütüphanesi, .NET projelerinde bu deseni kolayca uygulamanızı sağlar.

  • CQRS ile birlikte kullanıldığında, okuma ve yazma sorumluluklarını netleştirir.

By tanju.bozok

Software Architect, Developer, and Entrepreneur

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir