Die .NET Compiler Platform ermöglicht es, C#-Code programmatisch zu lesen und auch zu generieren. Dadurch ist es nicht nur möglich Code besser zu analysieren, sondern auch dynamisch zur Laufzeit neuen Code zu erzeugen.
Warum ein Artikel über Microsoft Roslyn? Weil mich das Thema unheimlich interessiert. Das erste Mal habe ich davon auf der TechEd 2010 gehört. Dort hat Anders Hejlsberg ein paar Worte zum Thema „Compiler as a Service“ verloren. Zwei Jahre später habe ich dann erstmals mit Roslyn in Form von der September 2012 CTP herumgespielt. Seit April 2014 ist Roslyn auch im Quellcode öffentlich verfügbar. Inzwischen ist Roslyn auf GitHub zu finden.
Aber was ist den überhaupt Microsoft Roslyn? Roslyn ist erstmal eine komplette Neuentwicklung der beiden C# und VB.NET Compiler. Der Code selbst ist, anders als bei den Vorgängern nicht mit C++, sondern komplett in C# geschrieben. Aber das ist nicht das Besondere. Dies steckt viel mehr im modularen Aufbau von Microsoft Roslyn. Das bedeutet, dass einzelne Teile des Compilers in eigenen Tools verwendet werden können. So kann damit der Quellcode analysiert werden oder auch neuer Code generiert werden. Seit dem Release ermöglicht diese eine Vielzahl neuer Tools und Visual Studio-Erweiterungen, da das Parsen und Generieren von Quellcode nun fast so einfach ist, wie das Verarbeiten von XML-Daten. Natürlich brachte Microsoft Roslyn darüber hinaus mit C# 6 und VB.NET 14 auch einige schöne Sprachfeatures, wie z. B. den Elvis-Operator.
Und wie kann ich nun Microsoft Roslyn verwenden? Wer Code selbst parsen oder generieren will, kann die nötigen Assemblies via NuGet installieren. Dies funktioniert seit VS 2015 ohne Probleme. Die Installation der Assemblies geht am besten über die NuGet „Packet Manager Console“.
Dort ist dann folgendes einzugeben:
Install-Package Microsoft.CodeAnalysis
Hier ein Beispiel. Es handelt sich dabei um eine kleine Anwendung, die alle Klassen in einem Sourcecode ausgibt. Das vollständige Projekt kann auf GitHub heruntergeladen werden.
using System;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
internal class Program
{
private static void Main()
{
SyntaxTree tree = CSharpSyntaxTree.ParseText(
@"using System;
class Program
{
static void Main()
{
Console.WriteLine(""Hallo, Welt!"");
}
}");
var root = tree.GetRoot();
foreach (var node in root.DescendantNodes().OfType<ClassDeclarationSyntax>())
{
Console.WriteLine(node.Identifier);
}
}
}
Program
Anmerkung: Bei diesem Text handelt es sich um einen überarbeiteten Repost eines alten Blog-Artikels aus 2015 von mir.