本文 适用于: ✔️ .NET 10 SDK 及更高版本
基于文件的应用使你可以从单个 C# 文件生成、运行和发布 .NET 应用程序,而无需创建传统的项目文件。 它们提供传统 .NET 项目的轻型替代方法。 此方法简化了脚本、实用工具和小型应用程序的开发。 .NET SDK 会根据源文件中的指令自动生成必要的项目配置。
主要优势包括:
- 减少了简单应用程序的样板代码。
- 具有嵌入式配置的自包含源文件。
- 默认情况下启用本机 AOT 发布。
- 自动打包为 .NET 工具。
本文介绍如何有效地创建、配置和使用基于文件的应用。
支持的指令
基于文件的应用使用带有 #: 前缀的指令来配置生成并运行应用程序。 支持的指令包括: #:package、 #:project、 #:property和 #:sdk。 将这些指令放在 C# 文件的顶部。
#:package
向应用程序添加 NuGet 包引用。
#:package Newtonsoft.Json
#:package Serilog@3.1.1
#:project
引用包含项目文件的另一个项目文件或目录。
#:project ../SharedLibrary/SharedLibrary.csproj
#:property
设置 MSBuild 属性值。
#:property TargetFramework=net10.0
#:property PublishAot=false
#:sdk
指定要使用的 SDK。 默认为 Microsoft.NET.Sdk。
#:sdk Microsoft.NET.Sdk.Web
#:sdk Aspire.AppHost.Sdk@13.0.2
CLI 命令
.NET CLI 通过熟悉的命令完全支持基于文件的应用。
运行应用程序
使用包含选项的 dotnet run 命令 --file 运行基于文件的应用:
dotnet run --file file.cs
或者使用dotnet run命令,并随后加上文件名:
dotnet run file.cs
也可以使用简写语法:
dotnet file.cs
传递参数
通过将参数放在--之后来传递给应用程序:
dotnet run file.cs -- arg1 arg2
如果没有 --,参数将转到 dotnet run 命令:
dotnet run file.cs arg1 arg2
生成应用程序
使用 dotnet build 以下命令编译基于文件的应用:
dotnet build file.cs
SDK 生成虚拟项目并生成应用程序。 默认情况下,生成输出将转到系统的临时目录下 <temp>/dotnet/runfile/<appname>-<appfilesha>/bin/<configuration>/。
将 --output 选项与命令一起使用 dotnet build 以指定其他路径。 若要定义新的默认输出路径,请使用指令设置OutputPath文件顶部的属性: #:property OutputPath=./output
清理生成输出
使用 dotnet clean 命令删除构建产物:
dotnet clean file.cs
删除目录中基于文件的应用的缓存:
dotnet clean file-based-apps
将 --days 选项与前面的命令一起使用,以指定在删除项目文件夹之前需要未被使用多少天。 默认天数为 30。
发布应用程序
基于文件的应用程序默认启用本机提前编译 (AOT) 发布,生成优化的自包含可执行程序。 通过在文件顶部添加 #:property PublishAot=false 来禁用此功能。
dotnet publish使用命令创建独立的可执行文件:
dotnet publish file.cs
可执行文件的默认位置是 artifacts 文件旁边的 .cs 目录,其子目录以应用程序命名。 将 --output 选项与命令一起使用 dotnet publish 以指定其他路径。
打包为工具
使用 dotnet pack 以下命令将基于文件的应用打包为 .NET 工具:
dotnet pack file.cs
默认情况下设置 PackAsTool=true 基于文件的应用。 通过在文件顶部添加 #:property PackAsTool=false 来禁用此设置。
转换为项目
使用 dotnet project convert 以下命令将基于文件的应用转换为传统项目:
dotnet project convert file.cs
此命令会复制.cs文件,并根据原始文件的#:指令创建一个包含等效 SDK 项、属性和包引用的.csproj文件。 这两个文件都放置在以应用程序命名的目录中,位于原始文件 .cs 旁,该原始文件保持不变。
还原依赖项
使用 dotnet restore 命令还原文件中引用的 NuGet 包:
dotnet restore file.cs
默认情况下,在生成或运行应用程序时,系统会自动执行还原操作。 可以将 --no-restore 传递给 dotnet build 和 dotnet run 命令,以便在无需隐式执行还原的情况下进行生成或运行。
默认包含的项目
基于文件的应用会自动包含用于编译和打包的特定文件类型。
默认情况下,包含以下项:
- 单个 C# 文件本身。
- 同一目录中的 ResX 资源文件。
不同的 SDK 包括其他文件类型:
-
Microsoft.NET.Sdk.Web包括*.json配置文件。 - 其他专用 SDK 可能包括其他模式。
本机 AOT 发布
默认情况下,文件型应用程序启用本地预先(AOT)编译。 此功能生成经过优化的自包含可执行文件,且启动速度更快,内存占用量更小。
如果需要禁用本机 AOT,请使用以下设置:
#:property PublishAot=false
有关本机 AOT 的详细信息,请参阅 本机 AOT 部署。
用户机密
基于文件的应用根据完整文件路径的哈希生成稳定的用户机密 ID。 此 ID 允许将敏感配置与源代码分开存储。
访问用户机密的方式与传统项目相同:
dotnet user-secrets set "ApiKey" "your-secret-value" --file file.cs
列出基于文件的应用的用户机密:
dotnet user-secrets list --file file.cs
通过 dotnet user-secrets list 命令可以输出您的机密值。 不要在公共上下文中运行的脚本中放置此命令。
有关详细信息,请参阅 开发中的应用机密的安全存储。
启动配置
基于文件的应用支持启动配置文件,用于配置应用程序在开发期间运行方式。 相较于将启动配置文件放在Properties/launchSettings.json中,基于文件的应用程序可以在与源文件相同的目录中使用一个名为[ApplicationName].run.json的平面启动设置文件。
基本启动设置文件
创建以应用程序命名的启动设置文件。 例如,如果基于文件的应用是 app.cs,请在同一目录中创建 app.run.json :
{
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
多个基于文件的应用
在同一目录中有多个基于文件的应用时,每个应用都可以有自己的启动设置文件:
📁 myapps/
├── foo.cs
├── foo.run.json
├── bar.cs
└── bar.run.json
用户配置选择
.NET CLI 使用以下优先级选择启动配置文件:
- 由
--launch-profile选项指定的配置文件。 - 由
DOTNET_LAUNCH_PROFILE环境变量指定的配置。 - 启动设置文件中第一个定义的配置文件。
为了按特定配置文件运行,请执行以下操作:
dotnet run app.cs --launch-profile https
传统启动设置
基于文件的应用还支持传统 Properties/launchSettings.json 文件。 如果这两个文件都存在,则传统位置优先。 如果这两个文件都存在,.NET CLI 会记录警告,以阐明使用哪个文件。
Shell 执行
使用 shebang 行和可执行权限,在类似 Unix 的系统上直接执行基于文件的应用。
在文件顶部添加 shebang:
#!/usr/bin/env dotnet
#:package Spectre.Console
using Spectre.Console;
AnsiConsole.MarkupLine("[green]Hello, World![/]");
使文件具有可执行属性:
chmod +x file.cs
直接运行:
./file.cs
注释
添加 shebang 时,请使用 LF 行尾而不是 CRLF。 不要在文件中添加 BOM。
隐式生成文件
基于文件的应用遵循同一目录或父目录中的 MSBuild 和 NuGet 配置文件。 这些文件会影响 SDK 如何生成应用程序。 组织基于文件的应用时,请注意这些文件。
Directory.Build.props
定义应用于目录树中的所有项目的 MSBuild 属性。 基于文件的应用继承这些属性。
Directory.Build.targets
定义 MSBuild 目标和自定义生成逻辑。 基于文件的应用在生成过程中执行这些目标。
Directory.Packages.props
为 NuGet 依赖项启用中央包管理。 基于文件的应用可以使用集中管理的包版本。
nuget.config
配置 NuGet 包源和设置。 还原包时,基于文件的应用使用这些配置。
global.json
指定要使用的 .NET SDK 版本。 基于文件的应用遵循此版本选择。
生成缓存
.NET SDK 缓存生成输出以提高后续调用 dotnet run的性能。 此缓存系统对于基于文件的应用是唯一的。
缓存行为
SDK 基于以下项缓存构建输出:
- 源文件内容。
- 指令配置。
- SDK 版本。
- 隐式构建文件的存在和其内容。
缓存可提高生成性能,但在以下情况下可能会导致混淆:
- 对隐式生成文件的更改不会触发重新生成。
- 将文件移动到不同的目录不会使缓存失效。
解决方法
- 使用以下命令清除文件型应用的缓存工件:
dotnet clean file-based-apps
使用
--no-cache标志运行完整构建:dotnet build file.cs --no-cache强制执行清理构建以绕过缓存:
dotnet clean file.cs dotnet build file.cs
文件夹布局建议
仔细组织基于文件的应用,以避免与传统项目和隐式生成文件冲突。
避免项目文件重叠
不要将基于文件的应用放置在项目的目录结构 .csproj 中。 项目文件的隐式生成文件和设置可能会干扰基于文件的应用。
❌ 不建议:
📁 MyProject/
├── MyProject.csproj
├── Program.cs
└──📁 scripts/
└── utility.cs // File-based app - bad location
✅ 推荐:
📁 MyProject/
├── MyProject.csproj
└── Program.cs
📁 scripts/
└── utility.cs // File-based app - good location
注意隐式文件
父目录中的隐式生成文件会影响子目录中所有基于文件的应用。 如果需要不同的生成配置,请为基于文件的应用创建隔离目录。
❌ 不建议:
📁 repo/
├── Directory.Build.props // Affects everything below
├── app1.cs
└── app2.cs
✅ 推荐:
📁 repo/
├── Directory.Build.props
├──📁 projects/
│ └── MyProject.csproj
└──📁 scripts/
├── Directory.Build.props // Isolated configuration
├── app1.cs
└── app2.cs