What is aspect-oriented programming, and how do you do it in .NET?
Quick Answer
AOP factors out cross-cutting concerns — logging, caching, retry, transactions, validation — that would otherwise be scattered through every method. .NET has no built-in AOP; you achieve it with decorators, dynamic-proxy interceptors (Castle DynamicProxy), MediatR pipeline behaviours, ASP.NET Core filters/middleware, or a compile-time weaver (PostSharp/Metalama).
Aspect-oriented programming is about pulling out the concerns that cut across everything — logging, caching, retries, wrapping things in a transaction — so they're not copy-pasted into every method. .NET doesn't have a language feature for it, so I use decorators — wrapping the real service in one that adds the behaviour and delegates — or interceptors where the container generates a proxy around every call. In a CQRS setup, MediatR pipeline behaviours are the natural place: one behaviour adds logging around every handler, another validation, another a transaction. The key is that the aspect stays pure plumbing with no domain logic in it.
- Decorator: wrap the real service in a class that adds the concern and delegates — explicit and testable.
- Interceptor: the container generates a proxy that runs your interceptor code around every method — less code, more magic.
- MediatR behaviours: one place to add logging/validation/transactions around every request handler.
- Keep aspects free of business logic — they're plumbing.