Multi-Platform

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.

Code Generation

Transforming Code

Override methods

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.

Override events

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.

Implement interfaces

You can implement an interface using an aspect. Here is an implementation of the C# Disposable pattern.

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.

Compile-Time Expressions

You can include compile-time expressions in run-time code, like this.MaxAttempts in the next example:

Compile-Time Loops and Conditions

Your template can have compile-time if and 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 TextWriter. Then, we use Invokers.Final.GetValue( meta.This ) to get the expression that represents this field. This expression returns a dynamic object, so any syntactically-valid C# on the right will be accepted.

Expression Builders

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.

Syntax Highlighting

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.

Suppress Warnings

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.

Eligibility

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.

Code Validation

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.

Fabrics

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.

Configure Aspects

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.

Interactive Assistance

Live Templates

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.

TODO

Debugging & Testing

Diff Preview

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.

Test Framework

You can unit test your aspects and check whether the generated code matches your expectations.

Introspection

LinqPad

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.

Introspection API

Did you like our LinqPad integration? Then be informed that you can do all these queries from your own application using Metalama Inspection API.

Metrics

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

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.

Unit-Tested Snippets

Most code snippets are unit tested using our test framework, so you can be almost sure that they work.

Online Sandbox

You can try and modify all examples yourself using our online sandbox.