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

Posted

技术标签:

【中文标题】通过 Visual Studio 2022 发布具有 C# 10 隐式使用的 .NET 6 项目【英文标题】:Publishing a .NET 6 project with C# 10 implicit usings via Visual Studio 2022 【发布时间】:2021-12-22 17:06:25 【问题描述】:

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

背景

C# 10 引入了新的implicit usings 功能,其中某些using 指令根据SDK 被视为global using directives。这可以通过以下csproj 配置启用:

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

这与本地构建完全一样。例如,当定位到 Microsoft.NET.Sdk.Web SDK 时,我可以删除 using 用于 SystemSystem.Collections.GenericSystem.Linq 等的指令。

发布错误

但是,当从 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 Studio\2022\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\6.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 新版本中的一项新功能,这可能是一个错误。也就是说,启用&lt;ImplicitUsing /&gt; 功能是否需要任何pubxml 属性?或者是否需要使用 Visual Studio 发布配置文件启用此功能?

【问题讨论】:

我假设问题是csc.exe 不知道csproj 文件本身,因此需要设置某种类型的标志来启用隐式使用。因此,接下来的步骤将是 a) 确定 csc.exe 上的标志是什么,以及 b) 如何通过 pubxml 设置该标志。除非社区通过发布解决方案来击败我,否则我明天会调查这两个问题。 【参考方案1】:

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

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

命令行参数

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

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

Microsoft 构建支持

相反,在处理 C# 项目文件 (*.csproj) 时,这是通过 Microsoft Build Engine (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) 的底层调用。

注意: .NET 6.0 SDK(即dotnet.exe)提供了一个围绕msbuild.exe 的包装器,作为buildpublish 的一部分命令,因此提供相同的功能。此外,默认情况下,.NET SDK 会将中间文件保存在 /obj 文件夹中,而 msbuild.exe 会立即删除它们。

C# 10 支持

鉴于此,隐式使用功能实际上并不是 C# 10 的一部分本身—despite being advertised as such—而是 Microsoft Build Engine 中内置的一些工具 (msbuild.exe) . C# 10 编译器 (csc.exe)确实支持global using directives,但不知道隐式使用。

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

结论

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

【讨论】:

以上是关于通过 Visual Studio 2022 发布具有 C# 10 隐式使用的 .NET 6 项目的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2022的一个惊艳新功能开发隧道

Visual Studio 2022 打包应用程序 - 解决方案资源管理器中缺少商店的“发布”

visual studio 的优点,请高手详细解答

Visual Studio 2022 for Mac v17.0 发布,离线安装包下载

Visual Studio 2022 正式版下载教程

Visual Studio 2022 正式版下载教程