PostSharp
PostSharp brings aspect-oriented programming to .NET. You write an aspect as a C# class, apply it with an attribute such as
[Log], and a post-compilation step rewrites the assembly to insert the behavior. It is a commercial product with a limited free edition.Paradigm: Aspect-Oriented Programming
What Makes PostSharp Special
- Aspects are attributes. Applying
[Log]to a method, a class or a whole assembly is enough. No pointcut language needs to be learned. - Compile-time weaving. After the C# compiler runs, PostSharp modifies the IL, so there is no proxy and no reflection at runtime.
- Ready-made patterns. Base classes such as
OnMethodBoundaryAspectandMethodInterceptionAspectcover logging, caching, retry, thread safety and transactions. - Attribute multicasting. One attribute can target many members at once:
[assembly: Log(AttributeTargetTypes = "MyApp.Services.*")]. - Architecture rules. It can also validate the design at build time, for example forbidding one namespace from using another.
Example: A logging aspect applied by attribute
using System;
using PostSharp.Aspects;
[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine($"Entering {args.Method.Name}");
}
public override void OnExit(MethodExecutionArgs args)
{
Console.WriteLine($"Leaving {args.Method.Name}");
}
}
public class Account
{
private decimal balance;
[Log]
public void Deposit(decimal amount)
{
balance += amount;
}
}
How It Works
LogAttributederives fromOnMethodBoundaryAspect, so PostSharp callsOnEntryandOnExitat the boundaries of any method it is applied to.[PSerializable]lets PostSharp store the aspect instance in the compiled assembly.[Log]onDepositis the only change to business code. The method body still only updates the balance.- After compilation, calling
Deposit(50)printsEntering DepositandLeaving Deposit, without any call to the aspect in the source.
History and Where It Is Used
PostSharp is used in enterprise .NET applications to remove boilerplate for logging, caching, threading, INotifyPropertyChanged and contracts. Alternatives include Fody and Castle DynamicProxy, and the .NET compiler now supports source generators for some of the same jobs.