Metalama 2023.3 introduces several new features: ready-made aspect implementations for caching and contracts, auxiliary templates, greatly revamped Metalama.Framework.Sdk
, and several enhancements and bug fixes.
Platform updates
- Roslyn 4.7.
- Visual Studio Code:
- C# Dev Kit is now supported.
- Omnisharp is deprecated and no longer tested.
- Visual Studio for Mac is deprecated and no longer tested, as Microsoft announced its sunsetting.
New Features
Auxiliary templates
It is now possible to call a template from a template. This allows to remove redundancy in templates and use abstraction and encapsulation thanks to virtual
templates and delegate-like template invocations.
For details, see Calling auxiliary templates.
Metalama.Patterns.Contracts
Metalama Contracts y is an open-source, aspect-oriented implementation of System.ComponentModel.DataAnnotations. Unlike Microsoft's annotations, Metalama Contracts works with any C# code, not just ASP.NET MVC or Entity Framework, as it utilizes aspects to inject validation logic during compilation.
In 2023.3, we are releasing Metalama.Patterns.Contracts
under the preview quality label. Conceptual documentation is not available at the moment. For conceptual documentation, see Metalama.Patterns.Contracts.
Metalama.Patterns.Caching
We've also ported our PostSharp-based caching framework to Metalama and completely open-sourced it. We updated the codebase to take full advantage of modern .NET and C#, including the use of IReadOnlySpan<char>
to further reduce garbage collection load.
As for contracts, we are currently releasing Metalama.Patterns.Caching
under the preview quality label. Conceptual documentation is not available at the moment. For conceptual documentation, see Metalama.Patterns.Caching.
Metalama.Framework.Sdk
You can now seamlessly use the Roslyn API for low-level code model analysis using the Metalama.Framework.Sdk
package. Although this package was available before, it wasn't directly accessible from an aspect project. That limitation has been removed.
For details, see Extending Metalama with the Roslyn API.
Enhancements
Debugging and troubleshooting
- In the error list, with most errors and warnings reported by aspects, you can now see which aspect class and target declaration reported the diagnostic.
- It is now possible to enable performance profiling of Metalama processes. See Capturing performance data for details.
- Visual Studio Tools for Metalama and PostSharp has improved reporting of errors in compile-time code.
- The debugging experience of templates and compile-time code has been dramatically improved. However, it is still required to use
Debugger.Break()
ormeta.DebugBreak()
to add an initial breakpoint.
Object model
- The IDeclaration interface has a new Sources property exposes references to the source code. You can now get any declaration's file path, line, and column.
- The Invoke method has a new overload that accepts an
IEnumerable<IExpression>
to generate dynamic method calls. - Invoking a method from the target type with InvokerOptions.Base and an instance (other than
base
) is now possible if the base layer is in the current type. - Any aspect can now reflect on any other IAspectInstance added before the current aspect thanks to the new API declaration.Enhancements().GetAspectInstances() returning an
IEnumerable<IAspectInstance>
. The previous method, GetAspects, did not return the IAspectInstance and gave no access to the IAspectState. - Metalama.Extensions.DependencyInjection: You can now introduce a dependency programmatically thanks to the TryIntroduceDependency method.
- New [RunTime] attribute that restricts to run-time the scope of a type that derives from a [RunTimeOrCompileTime] base class or interface.
- IAdviceFactory: introduction methods like IntroduceMethod now return the existing member even for AdviceOutcome.Ignore.
- AsyncEnumerableList<T>.AsyncEnumerator now has a Parent property which gets the AsyncEnumerableList<T> over which the enumerator enumerates. This allows methods such as BufferToListAsync (see below) to avoid creating a new AsyncEnumerableList<T> when an enumerator is already based on an AsyncEnumerableList<T>.
- The BufferToListAsync method has a new overload accepting an
IAsyncEnumerator<T>
which buffers an async enumerator into an AsyncEnumerableList<T>, and returns the list. This supports scenarios such as caching.
Performance
- The design-time performance of reference validators has been improved.
- Performance improvement of Metalama.Framework.Workspaces, especially useful while using the Metalama driver for LinqPad.
Other
- Overriding asynchronous methods with a template has been improved.
Breaking changes
There will be a few minor breaking changes in 2023.3. We think that there are still relatively few users and certainly little legacy code to maintain compatibility with, so we are prioritizing usability improvements over backward compatibility.
T#:
foreach
andwhile
expressions now give preference to run-time scope.Previously,
while ( true )
would be interpreted as a compile-time loop. Now, it will be considered as a run-time loop.Previously, the way to get a compile-time
for
loop was to do aforeach ( var in in Enumerable.Range(...) )
. Now,Enumerable.Range(...)
will be interpreted as run-time by default because it is inside aforeach
, so you need to specifically mark it as compile-time usingforeach ( var in in meta.CompileTime( Enumerable.Range(...) ) )
.In EligibilityExtensions, the method overload
void MustSatisfy<T>( this IEligibilityBuilder<T> eligibilityBuilder, Action<IEligibilityBuilder<T>> requirement )
has been renamed to AddRules in order to avoid ambiguities with the first and principal overload of MustSatisfy.The
IDiagnosticSink
interface is now internal. The ScopedDiagnosticSink type is now used in all public APIs.The type
SyntaxReference
has been renamed SourceReference.
Bug fixes & changelogs
For a detailed list of bugs fixed in this release, see the detailed changelogs: