Metalama works on Windows, Linux, and OSX. You can use Visual Studio, Rider, or Visual Studio Code.
Althought you need Visual Studio for the full experience, most features are IDE-agnostic and will work with any Roslyn-enabled editor.
Override any method with a simple code template. The grayed code is evaluated at compile time.
The template will also work on async methods and iterators.
Override properties and fields
You can override properties and fields using the same template.
You can also override events, but we are not completely done with this scenario.
Introduce methods, properties and fields
You can introduce members declaratively. Here is a simple implementation of
ToString that prints a quasi-unique identifier for each distinct instance.
You can also introduce members programmatically and customize its name and signature. For instance, we generate an
Update method that writes all mutable fields and properties.
You can implement an interface using an aspect. Here is an implementation of the C#
T# Templating Language
100% Correct C# Syntax
T# is pure C#, but it is compiled differently. You can use any C# editor, and there is no need to learn a new language.
You can include compile-time expressions in run-time code, like
this.MaxAttempts in the next
Compile-Time Loops and Conditions
Your template can have compile-time
foreach blocks. The next example prints the value of all parameters.
Call Target Code
Run-time code appears as
dynamic code to your template, so it
is easy to access it at compile-time if you know the member name. In the following example,
meta.This is a dynamic object that translates
into the run-time expression
this. So, you can access the
this._logger field of the target type without casting to the target type.
If you don't know the member name, you can generate calls dynamically using the code model. In this example, we first search for a field of type
Then, we use
Invokers.Final.GetValue( meta.This ) to get the expression that represents this field. This expression returns a
so any syntactically-valid C# on the right will be accepted.
You can parse any string into a
dynamic expression using
meta.ParseExpression. You can then use this expression in a template.
However, it is easier and safer to use helper classes like
InterpolatedStringBuilder in the following example.
When you install Metalama Tools for Visual Studio, you get beautiful highlighting of your T# code, just like in this documentation.
Errors & Warnings
Report Errors & Warnings
Your aspect can report a warning, error, or information. In the following aspect, we report an error when a required field is missing.
Your aspect can suppress a warning reported by the compiler, the IDE, or an analyzer. In the next example, we suppress the unused field warning from the IDE, because the field is used in the code generated by the aspect.
You can define on which declarations your aspect can be added by implementing the
BuildEligibility method. Metalama will report an error if someone tries to use the aspect on a non-eligible declaration. And of course, the IDE will suggest
to add the aspect only when it is relevant. For instance, the next aspect requires a non-static method.
You can validate how your code is being used, emit a warning when you detect a violation, and even suggest a code fix. For instance, the next aspect validates that a class member is only used in a test project.
The next aspect validates that its targets are used only in test projects. A clean way for an API author to document the intend.
Add Aspects and Validators in Bulk
With a project fabric or namespace fabric, you can add aspects and validators programmatically instead of doing it one-by-one using custom attributes.
In the following example, we are adding logging to all methods in the current project.
Enhance the Current Type
You can transform the current type and introduce new members programmatically without having to create an aspect class.
The next example declares 10 repetitive methods in a type.
Using a project fabric or a transitive project fabric, you can create a compile-time configuration API for your aspect.
The following example exposes an option that sets the default logging category.
Any aspect can be applied to source code instead of being transparently applied to the executed code. We call that a live template. The live template will be proposed in the code refactoring (lightbulb) menu.
Code Fixes & Refactorings
Any aspect or validator can attach code fixes to any warning, error or information it reports. It can also suggest a code fix without any message.
Debugging & Testing
You can preview the transformed code (the one generated by Metalama, which will be executed) and compare it to your source code directly from Visual Studio.
Debug Source Code
That seems obvious, but this was not easy to implement. You can debug by stepping into your source code, even if the code being executed is different.
Debug Transformed Code
You can also debug by stepping into the transformed code, so you see exactly what is happening.
You can unit test your aspects and check whether the generated code matches your expectations.
You can load your .NET projects with LinqPad and explore the code model using C# and LINQ — just as if you would query a database. You can also inspect the aspects, the diagnostics, and diagnose tricky issues without starting the debugger.
Did you like our LinqPad integration? Then be informed that you can do all these queries from your own application using Metalama Inspection API.
You can query code metrics, such as the number of syntax nodes or statements in a method body, from LinqPad or any other application. You can also define your own metrics.
Extensibile using Roslyn
While Metalama is a well-throught API for disciplined, high-level metaprogramming, you can go the extra mile and hack your own transformations or metrics using the Roslyn API. Yes, it voids the guarantee.
Here is what you can do with Metalama SDK:
- Custom aspects
- Custom metrics
- Custom code fixes
Documentation is a feature. We've tried hard to make it super easy to get started and to assist you in the most complex tasks.
Most code snippets are unit tested using our test framework, so you can be almost sure that they work.
You can try and modify all examples yourself using our online sandbox.