1. The Mediator pattern
The Mediator pattern in .NET Core is a behavioral design pattern that reduces coupling between components by forcing them to communicate indirectly through a central "mediator" object. Instead of classes having direct references to each other, they send messages to the mediator, which then routes them to the appropriate handlers.
Why Use It?
- Decoupling: Objects don't need to know about each other's existence or implementation details.
- Slim Controllers: In ASP.NET Core, it keeps API controllers thin by moving business logic into separate "handler" classes.
- Maintainability: Centralizing communication logic makes it easier to modify or extend individual components without ripple effects.
- CQRS Support: It is the standard way to implement Command Query Responsibility Segregation (CQRS), where "Commands" (writes) and "Queries" (reads) are handled separately
The Standard Implementation: MediatR
While you can build your own mediator, the MediatR NuGet package is the industry standard for .NET applications.
- Request/Command: A simple class representing the action you want to perform (e.g.,
CreateUserCommand). - Handler: A class implementing
IRequestHandler<TRequest, TResponse>that contains the actual business logic. - The Mediator: An
IMediatorinstance (injected via Dependency Injection) that sends the request to the correct handler.
2. Repository Pattern
The Repository Pattern is a design pattern that creates an abstraction layer between an application's business logic and its data access layer. It encapsulates the logic required to access data sources, allowing the rest of the application to treat data as a simple in-memory collection.
Core Benefits
- Separation of Concerns: Business logic remains independent of specific data access technologies like Entity Framework Core or Dapper.
- Maintainability: Centralizing data logic prevents duplication across multiple controllers or services.
- Testability: High-level components can be tested using mock repositories instead of a real database.
- Flexibility: You can swap the underlying data source (e.g., from SQL Server to MongoDB) without modifying the business logic.
Standard Implementation Steps
Implementation typically involves defining an interface and a concrete class that uses an ORM like EF Core.
- Define a Repository Interface: Create an interface (e.g.,
IProductRepository) that defines standard CRUD operations likeGetAllAsync,GetByIdAsync, andAddAsync. - Implement the Concrete Repository: Create a class that implements the interface and interacts with the
DbContext. - Register the Repository: In
Program.cs, use the built-in Dependency Injection container to register the repository as a scoped service. - Inject and Use: Inject the interface into your controllers or services via the constructor.
Common Variations
- Generic Repository Pattern: A single generic interface (
IRepository<T>) and class handle common operations for all entity types, reducing boilerplate code. - Unit of Work Pattern: Often used alongside repositories to group multiple repository operations into a single transaction.
- Specification Pattern: Used with generic repositories to encapsulate complex query logic into reusable objects
Comments
Post a Comment