New in PostSharp 4.0: Aspect Repository

by Gael Fraiteur on 14 Oct 2014

When we built the undo/redo and threading models features of PostSharp 4.0, we needed had to address the problem of aspect dependencies. Both the Recordable and threading models aspects require the Aggregatable aspect. If the Aggregatable aspect is not present, it should be added automatically.

Checking whether an aspect has been added to a declaration

Adding a dependent aspect automatically is easy: it can be done with the IAspectProvider. What’s more difficult is to know whether an aspect has already been added to a declaration. The aspect can have been added as a custom attribute, as a multicast custom attribute, and in these cases the ReflectionSearch.GetCustomAttributesOnTarget method would do the job. But they also be added dynamically using through IAspectProvider, and up to now there was no API to reflect dynamically added aspects. That’s why we added the IAspectRepositoryService interface. It has two interesting features:

  • GetAspectInstances and HasAspect methods: Query aspects on a given declaration.
  • AspectDiscoveryCompleted event: Event raise after all aspects have been discovered and initialized.

To check whether an aspect has been added to a declaration, the following code is typically used in the implementation of IAspectProvider.

PostSharpEnvironment.CurrentProject.GetService<IAspectRepositoryService>.HasAspect( declaration, typeof(Aspect) )

Late validations

Sometimes it is necessary to programmatically validate code against the presence of aspects. This validation can be done only after all dynamic aspect providers (IAspectProvider) have been executed. For instance, child fields of an immutable class must have be themselves immutable or freezable, which means that, unless this is an intrinsically immutable type like int or string, the aspect must have the Immutable or Freezable aspect.

This is why we have the AspectDiscoveryCompleted event on the IAspectRepositoryService interface. It allows aspects to execute code at build time after all aspects have been discovered

Summary

Technically, the new service IAspectRepositoryService allows you to cope with complex dependencies between aspects. But more fundamentally, the feature allows you to create real language extensions composed of several aspects and custom attributes that play well together.

Happy PostSharping!

-gael