Metalama Status Update, October 2024

by Gael Fraiteur on 31 Oct 2024

As the .NET Conf 2024 approaches, we’ve made significant progress in supporting .NET 9.0 and C# 13 with both Metalama and PostSharp. But that’s not all. We’ve also filled usability gaps in introduced types and added several minor features. October was buzzing with community interactions: we hosted an event with Andrea Angella from Productive C#, exchanged blog posts with GoatReview, and published five articles on our own.

PostSharp 2025.0 Preview

We’ve been updating PostSharp to the new .NET stack and have now fully caught up with .NET 9.0 RC2.

Additionally, we’ve worked on the following improvements:

  • Long path support: Previously available only for .NET Core and .NET Standard projects, long paths are now supported in projects targeting .NET Framework.
  • Improved Windows PDB support: We’ve revamped our Windows PDB writer, which now supports modern features like embedded sources or compiler info. This update also fixes bugs and incompatibilities with tools in previously supported features.

We consider ourselves done with PostSharp 2025.0 and plan to announce its general availability in the first week of January.

Metalama 2025.0 Preview

We’ve focused on two areas. First, ensuring Metalama is compatible with the latest .NET stack. Second, completing gaps left in the previous version, particularly in support for type introductions. We’ve also implemented minor improvements requested by the community.

We published the following preview builds: 2025.0.1-preview, 2025.0.2-preview, 2025.0.3-preview, and 2025.0.4-preview.

Platform upgrade

Regarding the platform update, we’re now completely done with supporting the upcoming .NET 9 and C# 13. We’re only waiting for the official GA release, expected mid November.

  • .NET 9.0 RC2 is supported.
  • C# 13:
    • Params collections
    • Ref/unsafe in iterators/async
    • Ref struct interfaces
    • Escape character
    • Method group natural type improvements
    • Lock object
    • Implicit indexer access in object initializers
    • Overload resolution priority
    • Partial properties
  • Platform deprecation:

    • The minimal supported Visual Studio version is now 2022 17.6 LTSC.
    • The minimal supported Roslyn version is now 4.4.0.
  • Third-party package dependencies have been updated.

Source generators and interceptors

We now consistently execute source generators after any Metalama transformation. Previously, code generators were executed before Metalama at build time, causing inconsistencies with the design-time experience, as Metalama would not “see” the output of source generators.

The benefit for you is that aspects can introduce code that relies on the GeneratedRegex attribute to use build-time-generated regular expressions.

The second benefit is that you can now use Roslyn interceptors side-by-side with Metalama since they no longer conflict with our code transformations.

Filling code model gaps

You can now use introduced types in any type construction. For instance, if Foo is your introduced type, you can create a field or parameter of type Foo<int>, Foo[], List<Foo>, or Foo*. This required a major refactoring of our code model.

You can also implement generic interfaces bound to a type parameter of the target type. For instance, you can now build an Equatable aspect that generates code for the IEquatable<T> interface, even for introduced types.

Defining local variables

It’s now possible to dynamically define local variables with the following new methods:

// Explicitly typed
meta.DefineLocalVariable( string nameHint, IType type ) : IExpression
meta.DefineLocalVariable( string nameHint, IType type, dynamic? initializerExpression ) : IExpression
meta.DefineLocalVariable( string nameHint, IType type, IExpresson? initializerExpression ) : IExpression
meta.DefineLocalVariable( string nameHint, Type type ) : IExpression
meta.DefineLocalVariable( string nameHint, Type type, dynamic? initializerExpression ) : IExpression
meta.DefineLocalVariable( string nameHint, Type type, IExpression? initializerExpression ) : IExpression

// var typed
meta.DefineLocalVariable( string nameHint, dynamic? initializerExpression ) : IExpression
meta.DefineLocalVariable( string nameHint, IExpresson? initializerExpression ) : IExpression

The nameHint parameter suggests the desired local variable name, but the actual name will be chosen dynamically by appending a numerical suffix in case of lexical conflicts with other symbols in the scope.

Clean up of the representation of overridden fields

When you override a field, Metalama turns it into a property. That is, an object of IField type before the aspect will be represented as an IProperty after the aspect. This usually works well, and most of you likely haven’t had to think much about it.

However, the devil is in the details. If you take a reference to a field before the aspect, you will get an IRef<IField>. If you resolve the reference after the aspect, you could previously run into a problem because the new IProperty could not be cast into an IField.

This tricky part of the code model has been redesigned. If you attempt to resolve an IRef<IField> reference to an overridden field, you will get an IField shim representing what is actually an IProperty. However, this object is not navigable through the INamedType.Fields properties, but only, as an IProperty, through INamedType.Properties. You can navigate to the “real” property using the IField.OverridingProperty property. The inverse relationship is the IProperty.OriginalField property. Also, the IRef.As<T>() method is able to convert an overridden IField into its overriding IProperty and conversely.

Other small improvements

  • Test framework: Added test options @Repeat(<int>) and @RandomSeed(<int>) to help reproduce random issues.
  • Code model: ToDisplayString and ToString implemented for introduced declarations.

Bugfixing releases

While busy with the 2025.0 versions, we published several bugfixing builds in stable releases:

Community News

Why did Cyril Canovas switch from Fody to Metalama for caching?

Cyril Canovas

Cyril Canovas is a contributing author at GoatReview 🐐, a technical blog focused on sharing in-depth developer experiences and best practices in .NET development.

A few months ago, Cyril explored Fody as a solution to generate the caching boilerplate. That was before he discovered Metalama. Yesterday, Cyril published an article on our blog explaining why he prefers Metalama over Fody to handle his caching boilerplate.

On the flip side, we published a two-part series introducing Metalama to GoatReview readers:

Presenting Metalama to the Productive C# community

Andrea Angella

This month, I had the honor of presenting Metalama to the members of the Productive C# community, a group of developers striving to become better C# developers under the expert leadership of former six-time Microsoft MVP Andrea Angella. If you’re struggling to keep up with the ever-increasing flow of C# features, check out his free course on Modern C#.

My presentation had two parts. The first part was public and demonstrated the principal Metalama features. The second part, exclusive to premium members, opened the hood and explained how Metalama works and how it integrates with Roslyn.

You can watch the first part on Productive C#’s YouTube channel.

Five published articles

Following a quieter end of summer, we’re back in full swing, publishing articles in our Timeless .NET Engineer series. This month, we focused on INotifyPropertyChanged and the Builder pattern. True llamas will notice that we publish articles in pairs: one Metalama-oriented and the other general. Big thanks to Darío Macchi for his invaluable help in creating the content.

4 Ways to Implement INotifyPropertyChanged Implement INotifyPropertyChanged with Metalama The Builder Pattern in C# [2024] Implementing the Builder pattern with Metalama Why I switched from Fody to Metalama for method caching

Summary

We’ve achieved most of the features we set out for Metalama and PostSharp 2025.0, and are now focusing on testing and stabilization. We’re confident we’ll be ready for the .NET Conf event in November when the General Availability of .NET 9 is expected to be announced. Additionally, we’ve made strides in bridging the remaining gaps between Metalama and “bare metal” Roslyn generators.

Happy meta-programming!

-gael

This article was first published on a https://blog.postsharp.net under the title Metalama Status Update, October 2024.