Announcing PostSharp "Caravela" Preview 3 (0.4)

by Gael Fraiteur on 11 Nov 2021

A new preview of PostSharp “Caravela”, our new Roslyn-based meta-programming framework, is now available. Caravela is the successor of the MSIL-based PostSharp Framework. It should work with most codebases, support the complete C# 9 language, and has a very respectable set of aspect-oriented features. This preview is the last we’re releasing under the codename “Caravela”. You can try Caravela today on sample projects, but it is not recommended to use it in production projects.

The following resources are available:

Please subscribe to our newsletter to stay informed about our progress with this project.

So, what features are already available?

Overriding methods

Override any method with a simple code template:

The template will also work on async methods and iterators:

Overriding properties

Override the implementation of a field or property. If the examples above were annoyingly simple, here’s a more complex example that demonstrates the implementation of that and shows how to automatically generate code that calls a service locator.

Introducing members and implementing

Your aspect can generate new methods, properties, fields or events. It can make the target type implement a new interface. The following example goes further in complexity and implements the deep cloneable pattern.

Authoring complex code templates

Code templates can have compile-time conditions, loops, variables, lambda expressions, and more. Code template can contain dynamic code to bind to the target code.

Even if the features of the template language are impressing, there will be times when it will be more convenient to generate code using an interpolated string, a StringBuilder, or a similar classical mechanism. For these situations, you can parse any string containing C# code into an expression or statement, then use it in C# just like other expression.

The template language offers helper classes to generate run-time expressions like arrays or, as in the following examples, interpolated strings:

You can easily convert compile-time objects, such as collections, intrinsic types or reflection types, to C# expressions. You can even define custom converters for your own classes. The following example demonstrates the conversion of the system type Dictionary and a custom type. It also shows how to programmatically generate expressions.

Defining eligibility

Aspects can define onto which declarations they want to be applied.

Reporting and suppressing diagnostics

Aspects can report warnings and errors. They can also suppress warnings reported by the C# compiler or other analyzers. In this example, we revisit a previous example and add some validation.

It’s perfectly fine to create an aspect that only analyzes the code and reports diagnostics, without transforming the code.

Adding aspects in bulk using fabrics

If you don’t want to add a custom attribute on each method to add your logging aspect, no problem. Fabrics have you covered. In the following example, we are adding the Log aspect to all methods of the current project.

Configuring aspects

You can create a configuration API for your aspects or just consume MSBuild properties.

Type fabrics

Without defining an aspect class, you can programmatically introduce new members, override existing members or report warnings in the current type by just defining a nested class.

Performing arbitrary modifications to code

Caravela’s philosophy is to offer a well-mannered API to express code transformations safely, without changing the code semantics, and in a composable way (which means that you can safely add to the same declaration several aspects that don’t know about each other). However, if you feel brave, you can shortcut the safety features and implement your code transformations directly using the Roslyn API. Anything you could do with an IL weaving tool like Cecil, Fody, CCI or PostSharp can now be done with Caravela. The documentation of this feature is severely outdated but you can have a look at the ConfigureAwait example.

Modifying source code with an aspect at design time

All of the examples above only modify intermediate code, not the source code, which keeps things clean and readable. We call this a live template because an aspect, by definition, does not modify the source code. However, any aspect can be used as a live template.

Live template

Previewing the transformed code

You can compare the source code with the code being executed.

Diff

Syntax highlighting of aspect code

Aspects are like code templates that mix run-time code with compile-time code, but without any markup tags. To help you understand which expressions and statements are compile-time, and which are just normal, we built a Visual Studio extension that colors the aspect code.

Diff

Debugging the source or transformed code

You can choose to debug the source or transformed code.

Debugging

Testing aspects

You can test your aspects with exactly the same testing framework we use internally. A test case generally includes a source file and an expected transformation file. The test succeeds if your aspect transformed the source file into the expected transformation file.

Debugging

What does not work yet

Although the list of features that work is already long, now is not the time to use Caravela in your production projects:

  • Licensing is not yet implemented. You cannot buy it, but you can use it for free under the evaluation license.
  • It’s not the final name! “Caravela” is a code name, and we still need to reveal the final name and rename all packages and namespaces.
  • Logging and telemetry is not yet implemented, so we cannot assist users in troubleshooting, and cannot pro-actively debug.
  • It’s largely untested with large projects and solutions – mostly just unit tests and sample projects.
  • Aspect initialization is not yet implemented.
  • You cannot yet add aspects to operators and constructors.
  • There are some gaps in the design-time experience.
  • We still want to add more features into code validation and design-time code generation.

Summary

This is the last preview of “Caravela” under the project codename and there is almost a stack overflow of features! In a couple of weeks, we will reveal the final product name and a few licensing options. All I can say for now is that a lot of these features will be available for free for everybody – from individuals to corporations.

We’d love your feedback on GitHub, Gitter or as a comment on this page.

Please subscribe to our newsletter to stay informed about our progress with this project.

Happy PostSharping!

-gael