PostSharp 2027.0 lets aspects receive services through constructor injection
PostSharp 2027.0 lets aspects request services from the dependency injection container. The build adds those services as constructor parameters of the enhanced class, so aspects no longer need a global service locator. Legacy code can migrate gradually, and PostSharp Caching can take its backend from the container too.
Key points
- Request services by returning ImportDependencyAdviceInstance from IAdviceProvider.ProvideAdvices.
- Use IsRequired = false for optional services and IsLazy = true to resolve a service on first use.
- The build adds constructor parameters; the original signature becomes a protected internal forwarder.
- Code using new falls back to RunTimeServiceLocator, so register its services at startup.
- Set UseDependencyInjection on [CacheConfiguration] to take ICachingService from the container.
- Available from PostSharp 2027.0.6-preview.
PostSharp aspects were hard to combine with dependency injection: they are built at compile time and stored statically, so constructor-based containers could never supply them with services. PostSharp 2027.0 closes that gap. An aspect returns an ImportDependencyAdviceInstance from IAdviceProvider to request a service, and the build adds a matching constructor parameter to the target class. Services can be required, optional or lazy.
Your class declares its own dependencies as usual, and the container registers the services. Code that still calls new gets null for those parameters and falls back to a process-wide RunTimeServiceLocator, enabling gradual migration. PostSharp Caching uses the same mechanism through UseDependencyInjection, so each container owns its cache. Static methods cannot receive constructor services and use a process-wide default instead, flagged by warning CAC011.
Real-world use
- An audit aspect on service methods that writes to a per-container IAuditLog, so tests do not share logs.
- A caching aspect on repository-style classes whose cache backend is configured in the composition root.
- Migrating a ten-year-old codebase where some classes come from the container and others still use new.
Why it matters
Aspects no longer hide dependencies behind a global locator, so tests can isolate them and startup order stops being fragile. Legacy code can move to DI one class at a time without rewriting every aspect.