Skip to content

PostSharp 2027.0.6-preview

Pre-release
Pre-release

Choose a tag to compare

@gfraiteur gfraiteur released this 22 Oct 19:17

PostSharp 2027.0.6-preview is based on v2027.0.5-preview, plus the following changes.

Highlights

  • Dependency injection in aspects. An aspect can now receive a service from dependency injection: the target class gets the service as a constructor parameter, and the advices read it (#318). [Cache] and [InvalidateCache] are the first aspects to use it: they can take their ICachingService from the container instead of a process-wide static (#323).
  • Background compilation server for .NET. Until now, only .NET Framework projects were compiled in a background pipe server. With dotnet build, .NET projects are now compiled in one too, on Windows, Linux and macOS, instead of in a new dotnet exec process for each project (#322).

Aspect framework

  • #316 New: [ImportMember] can be applied to the parameters of an advice method, so that a statically scoped aspect can read and write the members of its target class without an instance-scoped aspect. The type of the parameter selects what the advice receives: the value or the address of a field (T, in T, ref T, out T), the value of a property, an ILocationBinding<T>, an open delegate or an IMethodBinding for a method, or a Property<T> or Event<T> in an instance-scoped aspect. Without a name, a field or property is matched by its type.
  • #317 New: IntroduceFieldAdviceInstance, returned by IAdviceProvider.ProvideAdvices, introduces a field into the target class, so that a statically scoped aspect can keep per-object state in the target object. The request can reuse an existing field, which is how two aspects share a field, and the advices read the field with [ImportMember].
  • #318 New: ImportDependencyAdviceInstance lets an aspect receive a service from dependency injection. The target class gets a field and a constructor parameter of the service type, also pulled into its derived classes in the project, and the advices read the service with [ImportMember]. The original constructors are kept as non-public forwarders that resolve the service from the new RunTimeServiceLocator, so new in the project still works. Applying such an aspect to a public class changes its public constructors.
  • #324 Enhancement: the advices of an aspect are grouped by the new GroupingAdvice.Group property, which names the group of an advice, whatever the class that declares it. When Group is not set, an advice without a pointcut joins the group of its class that has no advice of its kind yet. Master and [SelfPointcut] are obsolete (CS0618). A redundant Group is reported as LA0255, two groups of one family that both apply to the target of the aspect as LA0257, Group and Master on one advice as LA0258, and two pointcuts in one group as LA0259. ⚠️ Breaking change: several [SelfPointcut] advices of different kinds without Master, such as an entry and an exit advice, now form one group instead of one group each, so they share their MethodExecutionArgs and MethodExecutionTag. Builds that use TreatWarningsAsErrors fail on the new warnings until the aspect is updated.
  • #325 Enhancement: [OnMethodInvokeAsyncAdvice] now accepts the [Declaration], [DeclarationName], [DeclarationIdentifier], [Arguments], [Argument] and [Binding] (as IAsyncMethodBinding) parameters, also in a generic advice method. The advice can return a Task<T> whose result becomes the result of the target; any other result type is reported as LA0287.
  • #328 Enhancement: set MatchPointcut.IsRequired to true to report LA0285 when the advice applies to no method, because no method has the name or no overload matches the advice.
  • #315 New: ProjectLocal<T> stores build-time state per project, for state that an aspect or a build-time service kept in a static field and that therefore leaked from one project to another processed by the same process.

Compiler

  • #322 New: with dotnet build, PostSharp compiles a .NET project in a long-running pipe server of the current user, instead of starting a dotnet exec process for each project. The server runs several compilations at a time, each in its own assembly load context, on Windows, Linux and macOS. On a small solution, a warm server compiled a project in 0.2 to 0.3 s instead of about 1 s. Set PostSharpUsePipeServer to False to compile with dotnet exec as before. Projects that target x86, and the MSBuild of Visual Studio, keep dotnet exec. postsharp shutdown also stops these servers. ⚠️ Breaking change: on by default.
  • #321 Fix: the compiler no longer shares its third-party dependencies, such as Newtonsoft.Json, System.Text.Json, System.Collections.Immutable or Microsoft.Extensions.DependencyInjection, with the project it compiles. On .NET Framework, a project that references a higher version of one of them no longer fails with PS0264, and the build-time code of a project runs against the versions that the project references. ⚠️ Breaking change: an add-in loaded with <Using> in PostSharp.config that relied on the compiler to supply one of these assemblies must ship it beside the add-in.

PostSharp.Patterns.Caching

  • #323 New: with [CacheConfiguration( UseDependencyInjection = true )], [Cache] and [InvalidateCache] use an ICachingService that the class receives from dependency injection, instead of the process-wide CachingServices.DefaultBackend, so each container has its own cache. Register the service with, for instance, services.AddSingleton<ICachingService>( new CachingService( backend ) ). Static methods and methods of structs fall back to CachingServices.DefaultService and are reported as CAC011, whose severity StaticMethodFallbackSeverity sets. Invalidating a method that uses the other service is CAC012. ⚠️ Breaking change: CacheAttribute and InvalidateCacheAttribute are now sealed and derive from MethodLevelAspect instead of MethodInterceptionAspect. CachingServices.DefaultBackend, DefaultKeyBuilder, some CachingServices.Invalidation overloads and the nested CachingServices.CachingProfileRegistry are obsolete; use CachingServices.DefaultService. An async iterator with [Cache] is now reported as CAC013 instead of LA0197.

PostSharp.Testing.AspectTesting

  • #326 New: the @CompareTransformedCode directive decompiles the woven assembly to C# and compares the declarations marked with // <target>, or all the top-level types of the file, with a .t.cs snapshot next to the test, which is accepted like the other expected files.

Resources