• .NET 10 Preview 6 run file 的一些优化
  • 发布于 11小时前
  • 11 热度
    0 评论
前言
.NET 10 在之前的 Preview 4 版本中开始引入 dotnet run file 支持,还不清楚的朋友可以先移步 你好 dotnet run file, 再见 csproj ,在 Preview 5/6 中又有一些优化来优化和改进使用体验,我们一起来看看有哪些改进

实战体验
在之前的版本中我们需要使用 dotnet run hello.cs 来执行单个文件,现在可以直接使用 dotnet hello.cs 了,对于 shebang 之前需要使用 #!/usr/bin/dotnet run 来指定使用 dotnet run 来执行,在 .NET 10 Preview 6 中我们可以去掉 run 直接使用 #!/usr/bin/dotnet 即可,这样使用起来更加的方便,可以像 node hello.js 一样使用了

例如:
#!/usr/bin/dotnet
Console.WriteLine("Hello .NET");


build/publish support
现在我们除了直接运行外,我们还可以使用 dotnet restore/build/publish

如果我们只想验证是否能够编译通过,那么我们就可以使用 dotnet build hello.cs 来验证了。除了这两个之外,值得一提的是支持 dotnet publish,可以将单个文件直接发布成可执行的应用程序,并且默认会启用 AOT 的发布。AOT 除 dotnet SDK 外需安装额外的编译工具链,详见:https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8&WT.mc_id=DT-MVP-5004222#prerequisites

publish 之后的大小只有 1.2 MB:

我们也可以使用在文件中指定 #property PublishAot=false 来不 publish aot,也可以 publish 的时候指定比如 :

dotnet publish hello.cs -p PublishAot=false

从 publish 的结果可以看出,没有 aot publish 的时候会有 runtimeconfig.json 以及 deps.json 文件输出,aot publish 的时候是没有的

Project reference support
现在可以引用某一个 project 了,可以指定到项目文件所在目录也可以指定到具体的项目文件,如下所示:
#:project ../Net10Samples
Net10Samples.JsonSamples.JsonIgnoreWhenReadWriteSample();

更多
除了上面的更新之外,还有一些更新,比如 SDK 也可以支持 version,这样也可以指定使用指定版本的 Aspire Sdk 了,比如: \#:sdk Aspire.AppHost.Sdk@9.3.1
#:property 指令现在需要 = 符号来分隔属性名称和值,以更好地与项目文件中的语法对齐,例如 #:property LangVersion=preview
另外现在支持执行没有扩展名的文件了,之前需要执行 .cs 文件,现在没有扩展名有 shebang 也可以执行
# 1. Create a single-file C# app with a shebang
cat << 'EOF' > hello.cs
#!/usr/bin/env dotnet
Console.WriteLine("Hello!");
EOF

# 2. Copy it (extensionless) into ~/utils/hello (~/utils is on my PATH)
mkdir -p ~/utils
cp hello.cs ~/utils/hello

# 3. Mark it executable
chmod +x ~/utils/hello

# 4. Run it directly from anywhere
cd ~
hello

最后我们可以在运行时获取到当前的 run file 的信息,示例如下:
#:property LangVersion=preview

Console.WriteLine("From [CallerFilePath] attribute:");
Console.WriteLine($" - Entry-point path: {Path.EntryPointFilePath()}");
Console.WriteLine($" - Entry-point directory: {Path.EntryPointFileDirectoryPath()}");

Console.WriteLine("From AppContext data:");
Console.WriteLine($" - Entry-point path: {AppContext.EntryPointFilePath()}");
Console.WriteLine($" - Entry-point directory: {AppContext.EntryPointFileDirectoryPath()}");

staticclassPathEntryPointExtensions
{
    extension(Path)
    {
        public static string EntryPointFilePath() => EntryPointImpl();

        public static string EntryPointFileDirectoryPath() => Path.GetDirectoryName(EntryPointImpl()) ?? "";

        private static string EntryPointImpl([System.Runtime.CompilerServices.CallerFilePath] string filePath = "") => filePath;
    }
}

staticclassAppContextExtensions
{
    extension(AppContext)
    {
        publicstaticstring? EntryPointFilePath() => AppContext.GetData("EntryPointFilePath") asstring;
        publicstaticstring? EntryPointFileDirectoryPath() => AppContext.GetData("EntryPointFileDirectoryPath") asstring;
    }
}

参考资料
• https://github.com/dotnet/core/blob/main/release-notes/10.0/preview/preview6/sdk.md#file-based-apps
• https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-10/sdk?WT.mc_id=DT-MVP-5004222
• https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8&WT.mc_id=DT-MVP-5004222#prerequisites
• https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/overview#file-based-programs
用户评论