Neu in .NET 10.0 [17]: NuGet-Pakete und Einstellungen fĂĽr File-based Apps
Informationen, die bei normalen .NET-Projekten in der Projektdatei .csproj liegen, setzt man in File-based Apps mit einer Präprozessor-Direktive.
(Bild: Pincasso/Shutterstock)
- Dr. Holger Schwichtenberg
Das direkte Ăśbersetzen und Starten von C#-Dateien nennt Microsoft File-based Apps. FĂĽr Informationen, die ĂĽblicherweise in der .csproj-Projektdatei liegen, hat Microsoft fĂĽr File-based Apps eine eigene Syntax eingefĂĽhrt.
Die Syntax beginnt mit der Raute # (eine Präprozessor-Direktive in C#) gefolgt von einem Doppelpunkt (aus der Sicht des C#-Compilers eine zu ignorierende Direktive):
- Festlegung des SDKs:
#:sdk Microsoft.NET.Sdk.Web. Bei der Angabe des SDK kann man ab Preview 6 auch die Versionsnummer nach @ angeben, beispielsweise#:sdk Aspire.AppHost.Sdk@9.3.1 - Referenz auf ein NuGet-Paket:
#:package Console@0.48.* - Referenz auf Projekte:
#:project ./ClassLib/ClassLib.csproj - Build-Eigenschaften, z. B. Versionsnummer:
#:property Version=1.1.2(vor Preview 6 noch ohne Gleichheitszeichen, sondern mit Leerzeichen als Trennung) - File-based Apps verwenden im Standard den NativeAOT-Compiler. Wenn man ihn mit
#:property PublishAot=falsedeaktiviert, wird der Just-in-Time-Compiler verwendet.
Videos by heise
Weitere Features von Files-based Apps sind:
- Man kann eine Datei .settings.json im gleichen Ordner mit den Settings fĂĽr die File-based App anlegen.
- Man kann in der Datei .run.json im gleichen Ordner ein Launch-Profil fĂĽr die File-based App anlegen.
- Man kann
dotnet build Dateiname.csoderdotnet restore Dateiname.csausfĂĽhren. - Man kann solche File-based Apps mit
dotnet publish cszu einer ausführbaren Datei (.EXE) übersetzen. - Innerhalb einer File-based App können Entwicklerinnen und Entwickler seit Preview 6 den Standort der Datei mit
AppContext.GetData("EntryPointFileDirectoryPath")und den ganzen Pfad zur ausgefĂĽhrten C#-Datei mitGetData("EntryPointFilePath")bestimmen. Das funktioniert allerdings nur mit File-based Apps, nicht in normalen, projektbasierten C#-Anwendungen.
Es gibt aber in .NET 10.0 noch keine Möglichkeit, in einer File-based App eine andere .cs-Datei direkt einzubinden. Das ist für .NET 11.0 geplant.
Folgender Code zeigt ein Beispiel einer File-based App mit zwei referenzierten NuGet-Paketen:
#!/usr/bin/env dotnet
#region Einstellungen fĂĽr File-based App
// https://www.nuget.org/packages/humanizer/
#:package Humanizer@2.14.1
// https://www.nuget.org/packages/Spectre.Console/
#:package Spectre.Console@0.*
#:property LangVersion=preview
#:property Version=1.2.0
#:project ./ClassLibrary/ClassLibrary.csproj
#endregion
using Spectre.Console;
using Humanizer;
var title = "C# Script v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version +
" mit " + System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription + "\n" +
AppContext.GetData("EntryPointFilePath");
// Header
AnsiConsole.Write(
new Panel(title)
.Header("[yellow]File-based App[/]", Justify.Center)
.Border(BoxBorder.Rounded)
.BorderStyle(new Style(foreground: Color.Green))
.Padding(1, 1, 1, 1)
);
// Parameter auflisten
foreach (var arg in args)
{
Console.WriteLine($"Argument: {arg}");
}
Console.WriteLine();
// Daten
(Data net80, Data net90, Data net10) = GetData();
// Textausgabe in Wochen
var dotNet8Released = DateTimeOffset.Parse(net80.Release);
TimeSpan dotNet8Since = DateTimeOffset.Now - dotNet8Released;
Console.WriteLine($"It has been {dotNet8Since.Humanize()} since .NET {net80.Version} was released.");
var dotNet9Released = DateTimeOffset.Parse(net90.Release);
TimeSpan dotNet9Since = DateTimeOffset.Now - dotNet9Released;
Console.WriteLine($"It has been {dotNet9Since.Humanize()} since .NET {net90.Version} was released.");
var dotNet10Released = DateTimeOffset.Parse(net10.Release);
TimeSpan dotNet10Since = DateTimeOffset.Now - dotNet10Released;
Console.WriteLine($"{dotNet10Since.Humanize()} since .NET {net10.Version} release.");
Console.WriteLine();
// Zeichne Balken für die Anzahl der Tage seit der Veröffentlichung
var bar = new BarChart()
.Width(100)
.AddItem("Days since .NET 8.0 release", dotNet8Since.TotalDays, Color.Red)
.AddItem("Days since .NET 9.0 release", dotNet9Since.TotalDays, Color.Blue)
.AddItem("Days since .NET 10.0 release", dotNet10Since.TotalDays, Color.Purple);
AnsiConsole.Write(bar);
Console.WriteLine();
// Lokale Funktion
static (Data, Data, Data) GetData()
{
var net80 = new Data
{
Version = "8.0",
Release = "2023-11-14"
};
var net90 = new Data
{
Version = "9.0",
Release = "2024-11-12"
};
var net10 = new Data
{
Version = "10.0",
Release = "2025-11-11"
};
return (net80, net90, net10);
}
// Datenklasse
class Data
{
public required string Version { get; set; }
public string Release { get; set; }
}
(rme)