通过 Visual Studio 2022 发布带有 C# 10 隐式用法的 .NET 6 项目

Publishing a .NET 6 project with C# 10 implicit usings via Visual Studio 2022

从 Visual Studio 2022 发布配置文件向 Azure 应用服务发布启用了 C# 10 <ImplicitUsings /> 的 ASP.NET Core 6 Web 应用程序时,由于缺少 using 语句。

背景

C# 10 引入了新的基于 SDK 的 implicit usings feature, where certain using directives are treated as global using directives。这可以通过以下 csproj 配置启用:

<PropertyGroup>
    <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

这与本地构建的预期完全一样。例如,当针对 Microsoft.NET.Sdk.Web SDK 时,我能够删除 SystemSystem.Collections.GenericSystem.Linq、&c.

using 指令

发布错误

但是,当从 Visual Studio 2022 发布配置文件发布到 Azure 应用服务时,构建输出显示如下错误:

C:\Code\MyWebApp\MyClass.cs(41,25): Error CS0246: The type or namespace name 'IEnumerable<>' could not be found (are you missing a using directive or an assembly reference?)

这可以在下面看到作为扩展上下文的一部分:

Build started...
1>------ Build started: Project: MyWebApp, Configuration: Release Any CPU ------
1>Done building project "MyWebApp.csproj".
2>------ Publish started: Project: MyWebApp, Configuration: Release Any CPU ------
Determining projects to restore...
All projects are up-to-date for restore.
C:\Program Files\Microsoft Visual Studio22\Professional\MSBuild\Current\Bin\Roslyn\csc.exe /noconfig /unsafe- /checked- /nowarn:1701,1702,1701,1702,2008 /fullpaths /nostdlib+ /platform:x64 /errorreport:prompt /warn:6 /define:TRACE;RELEASE;NET;NET6_0;NETCOREAPP;NET5_0_OR_GREATER;NET6_0_OR_GREATER;NETCOREAPP1_0_OR_GREATER;NETCOREAPP1_1_OR_GREATER;NETCOREAPP2_0_OR_GREATER;NETCOREAPP2_1_OR_GREATER;NETCOREAPP2_2_OR_GREATER;NETCOREAPP3_0_OR_GREATER;NETCOREAPP3_1_OR_GREATER /errorendlocation /preferreduilang:en-US /highentropyva+ /reference: /debug+ /debug:portable /filealign:512 /optimize+ /out:obj\Release\net6.0\win-x64\MyWebApp.dll /refout:obj\Release\net6.0\win-x64\ref\MyWebApp.dll /target:exe /warnaserror- /utf8output /deterministic+ /langversion:10.0 /analyzerconfig:… /analyzer:"C:\Program Files\dotnet\sdk.0.100\Sdks\Microsoft.NET.Sdk.Web\analyzers\cs\Microsoft.AspNetCore.Analyzers.dll" /additionalfile:Areas\MyArea\Index.cshtml … /warnaserror+:NU1605
C:\Code\MyWebApp\MyClass.cs(41,25): Error CS0246: The type or namespace name 'IEnumerable<>' could not be found (are you missing a using directive or an assembly reference?)
2>Build failed. Check the Output window for more details.
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
========== Publish: 0 succeeded, 1 failed, 0 skipped ==========

我认为这与发布配置文件生成的 csc.exe 命令有关。

发布资料

不幸的是,如何在我的 pubxml 文件中解决这个问题对我来说不是很明显,这非常简单:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>MSDeploy</WebPublishMethod>
    <ResourceId>/subscriptions/77e95f68-ed69-4bfe-9bbe-0b4d3910722e/resourceGroups/ResourceGroup/providers/Microsoft.Web/sites/MyWebApp</ResourceId>
    <PublishProvider>AzureWebSite</PublishProvider>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <ProjectGuid>77e95f68-ed69-4bfe-9bbe-0b4d3910722e</ProjectGuid>
    <MSDeployServiceURL>mywebapp.scm.azurewebsites.net:443</MSDeployServiceURL>
    <DeployIisAppPath>MyWebApp</DeployIisAppPath>
    <RemoteSitePhysicalPath />
    <SkipExtraFilesOnServer>False</SkipExtraFilesOnServer>
    <MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
    <EnableMSDeployBackup>True</EnableMSDeployBackup>
    <UserName>$MyWebApp</UserName>
    <_SavePWD>True</_SavePWD>
    <_DestinationType>AzureWebSite</_DestinationType>
    <TargetFramework>net6.0</TargetFramework>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
    <SelfContained>false</SelfContained>
    <InstallAspNetCoreSiteExtension>False</InstallAspNetCoreSiteExtension>
    <EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
  </PropertyGroup>
</Project>

(注意:ResourceIdProjectGuid 等已被匿名化,并不指代实际的 属性。)

问题

承认这是 Visual Studio 新版本中的一项新功能,这可能是一个错误。也就是说,启用 <ImplicitUsing /> 功能是否需要任何 pubxml 属性?或者是否需要其他东西才能使用 Visual Studio 发布配置文件启用此功能?

首先,这似乎是一场虚惊。在安装 Visual Studio 2022 的发布版本后,我显然忽略了完成重新启动我的工作站。重新启动后,我现在可以在完全支持隐式使用的情况下发布。哎呀

也就是说,这确实提供了一个很好的机会来提供一些关于我事后发现的见解,这可能会帮助未来遇到类似问题的读者——当然也有帮助我更好地理解了各种命令行工具之间的集成。

命令行参数

值得注意的是,似乎没有任何命令行 参数 用于处理内置于以下任何工具中的隐式使用:

  • .NET 6.0 SDK (dotnet.exe)
  • Visual C# 编译器(csc.exe
  • Microsoft 构建引擎 (msbuild.exe)

Microsoft 构建支持

相反,这是在处理 C# 项目文件 (*.csproj) 时通过 Microsoft 构建引擎 (msbuild.exe) 处理的,此时它会在以下位置生成以下中间文件:

/{BaseIntermediateOutputPath}/{Configuration}/net6.0/{MyWebApp}.GlobalUsings.g.cs

例如,默认情况下:

/obj/Release/net6.0/MyWebApp.GlobalUsings.g.cs

此文件包含特定于配置的 SDK 的全局 using 指令:

// <auto-generated/>
global using global::Microsoft.AspNetCore.Builder;
global using global::Microsoft.AspNetCore.Hosting;
…

反过来,此文件附加到对 C# 编译器 (csc.exe) 的基础调用。

Note: The .NET 6.0 SDK—i.e., dotnet.exe—provides a wrapper around msbuild.exe as part of either the build or publish commands, and thus offers the same functionality. Further, by default, the .NET SDK will persist the intermediate files in the /obj folder, whereas msbuild.exe immediately deletes them.

C# 10 支持

鉴于此,隐式使用功能实际上并不是 C# 10 的一部分本身despite being advertised as such—but is rather a bit of tooling built into the Microsoft Build Engine (msbuild.exe). The C# 10 compiler (csc.exe) does supports global using directives,但没有意识到 隐式 使用。

最终,这并不 令人惊讶,因为 C# 编译器 (csc.exe) 实际上并不知道 C# 项目文件 (*.csproj ) 本身——它们是 Microsoft Build Engine 的产物,通过 .NET SDK 提供传递支持。

结论

目前尚不清楚为什么本地构建在完全重启之前使用此功能成功运行,而使用 Visual Studio 2022 的发布配置文件的调用却失败了。我认为这与 Visual Studio 如何在发布过程中为 C# 编译器 (csc.exe) 组装参数有关。无论如何,安装后重新启动工作站是一个简单的解决方案。否则,这个 post 有望帮助揭开整个过程的神秘面纱。