File-based Apps in .NET 11 mit Projektreferenzen
- Matt
Ein dotnet run script.cs wächst irgendwann über sich hinaus. Solange nur ein NuGet-Paket fehlt, reicht #:package. Sobald man aber Code aus einer bestehenden Bibliothek wiederverwenden oder die Datei einfach in zwei Teile aufteilen will, war bisher Schluss - dann musste die Datei erst per dotnet project convert zu einem richtigen Projekt werden. In .NET 11 gibt es dafür zwei Direktiven, die unterschiedlich weit gehen.
#:project: eine vorhandene Bibliothek referenzieren
Wer schon eine Klassenbibliothek als .csproj hat, bindet sie direkt ein:
#:project ../SharedLibrary/SharedLibrary.csproj
using SharedLibrary;
Console.WriteLine(Greeter.Greet("Welt"));
Der SDK übersetzt das intern in ein ganz normales <ProjectReference>. Man kann auch nur den Ordner angeben (#:project ../SharedLibrary) - dann sucht der SDK darin nach genau einer Projektdatei. Liegen keine oder mehrere .csproj in dem Ordner, bricht der Build mit einem Fehler ab.
#:ref: eine zweite Datei ohne Projekt
Neu in .NET 11 ist #:ref. Damit referenziert man eine weitere lose .cs-Datei, ganz ohne Projektdatei dazwischen:
// helper.cs
#:property OutputType=Library
public static class Helper
{
public static void Print(string message) => Console.WriteLine(message);
}
// app.cs
#:ref helper.cs
Helper.Print("Hallo von app.cs");
Der SDK erzeugt für helper.cs im Hintergrund ein virtuelles Projekt (helper.cs.csproj) und hängt es als ProjectReference an. Die referenzierte Datei wird also als eigene Assembly kompiliert, entsprechend sind internal-Member aus helper.cs in app.cs nicht sichtbar. #:ref ist transitiv: Referenziert helper.cs seinerseits eine dritte Datei, wird die mitgezogen.
Der Haken
#:ref steht in .NET 11 noch hinter einem Feature-Flag. Ohne #:property ExperimentalFileBasedProgramEnableRefDirective=true (oder die entsprechende MSBuild-Property) am Anfang der Datei bleibt die Direktive wirkungslos. Für alles, was über ein Wochenendexperiment hinausgeht, würde ich aktuell zu #:project mit einer echten Bibliothek greifen - die Syntax dafür ist stabil, und man verliert beim späteren dotnet project convert nichts, weil das Tool auch mit #:ref-Dateien rekursiv umgehen kann, jede referenzierte Datei landet dann als eigenes Projekt im Zielverzeichnis.
Über das Laufenlassen einzelner Dateien ohne Projekt hatte ich schon im November geschrieben, damals ging es nur um #:package. Die Direktiven im Detail stehen in der Dokumentation zu File-based Apps, der aktuelle Stand von #:ref inklusive Feature-Flag im dotnet/sdk-Repository.