SDKs de projeto .NET

Projetos .NET modernos estão associados a um kit de desenvolvimento de software (SDK). Cada SDK de projeto é um conjunto de destinos MSBuild e tarefas associadas que são responsáveis pela compilação, empacotamento e publicação de código. Um projeto que faz referência a um SDK de projeto às vezes é chamado de um projeto no estilo SDK.

SDKs disponíveis

Os seguintes SDKs estão disponíveis:

ID Description Repositório
Microsoft.NET.Sdk SDK de .NET https://github.com/dotnet/sdk
Microsoft.NET.Sdk.Web O SDK da Web .NET https://github.com/dotnet/sdk
Microsoft.NET.Sdk.BlazorWebAssembly O SDK do .NET Blazor WebAssembly https://github.com/dotnet/aspnetcore
Microsoft.NET.Sdk.Razor O SDK do .NET Razor https://github.com/dotnet/aspnetcore
Microsoft.NET.Sdk.Worker O SDK do Serviço de Trabalho .NET

O SDK do .NET é o SDK base para .NET. Os outros SDKs fazem referência ao SDK do .NET e os projetos associados aos outros SDKs têm todas as propriedades do SDK do .NET disponíveis para eles. O SDK da Web, por exemplo, depende do SDK do .NET e do SDK do Razor.

Você também pode criar seu próprio SDK que pode ser distribuído via NuGet.

Para projetos Windows Forms e Windows Presentation Foundation (WPF), especifique o SDK do .NET (Microsoft.NET.Sdk) e defina algumas propriedades adicionais no arquivo de projeto. Para obter mais informações, consulte Habilitar o SDK do .NET Desktop.

Ficheiros de projeto

Os projetos .NET são baseados no formato MSBuild . Os arquivos de projeto, que têm extensões como .csproj para projetos C# e .fsproj para projetos F#, estão em formato XML. O elemento raiz de um arquivo de projeto MSBuild é o elemento Project . O Project elemento tem um atributo opcional Sdk que especifica qual SDK (e versão) usar. Para usar as ferramentas .NET e criar seu código, defina o Sdk atributo como uma das IDs na tabela SDKs disponíveis.

<Project Sdk="Microsoft.NET.Sdk">
  ...
</Project>

Para especificar um SDK que vem do NuGet, inclua a versão no final do nome ou especifique o nome e a versão no arquivo global.json .

<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
  ...
</Project>

Outra maneira de especificar o SDK é com o elemento de nível Sdk superior:

<Project>
  <Sdk Name="Microsoft.NET.Sdk" />
  ...
</Project>

Fazer referência a um SDK de uma dessas maneiras simplifica muito os arquivos de projeto para .NET. Ao avaliar o projeto, o MSBuild adiciona importações implícitas para Sdk.props na parte superior do arquivo de projeto e Sdk.targets na parte inferior.

<Project>
  <!-- Implicit top import -->
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
  ...
  <!-- Implicit bottom import -->
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

Gorjeta

Em uma máquina Windows, os arquivos Sdk.props e Sdk.targets podem ser encontrados na pasta %ProgramFiles%\dotnet\sdk\[version]\Sdks\Microsoft.NET.Sdk\Sdk .

Pré-processar o arquivo de projeto

Você pode ver o projeto totalmente expandido como o MSBuild o vê depois que o SDK e seus destinos são incluídos usando o dotnet msbuild -preprocess comando. A opção de pré-processo do dotnet msbuild comando mostra quais arquivos são importados, suas fontes e suas contribuições para a compilação sem realmente construir o projeto.

Se o projeto tiver várias estruturas de destino, concentre os resultados do comando em apenas uma estrutura especificando-a como uma propriedade MSBuild. Por exemplo:

dotnet msbuild -property:TargetFramework=net8.0 -preprocess:output.xml

O padrão inclui e exclui

O padrão inclui e exclui itensCompile, recursos incorporados e None itens são definidos no SDK. Ao contrário de projetos .NET Framework que não são SDK, você não precisa especificar esses itens em seu arquivo de projeto, porque os padrões abrangem os casos de uso mais comuns. Esse comportamento torna o arquivo de projeto menor e mais fácil de entender e editar manualmente, se necessário.

A tabela a seguir mostra quais elementos e quais globs são incluídos e excluídos no SDK do .NET:

Elemento Incluir glob Excluir glob Remover glob
Compile **/*.cs (ou outras extensões linguísticas) **/*.utilizador; **/*.*proj; **/*.sln; **/*.vssscc N/A
EmbeddedResource **/*.resx **/*.utilizador; **/*.*proj; **/*.sln; **/*.vssscc N/A
None **/* **/*.utilizador; **/*.*proj; **/*.sln; **/*.vssscc **/*.cs; **/*.resx

Nota

As ./bin pastas and ./obj , que são representadas $(BaseOutputPath) pelas propriedades e $(BaseIntermediateOutputPath) MSBuild, são excluídas dos globs por padrão. As exclusões são representadas pela propriedade DefaultItemExcludes.

O .NET Desktop SDK tem inclusões e exclusões adicionais para WPF. Para obter mais informações, consulte WPF default includes and excludes.

Se você definir explicitamente qualquer um desses itens em seu arquivo de projeto, é provável que obtenha um erro de compilação NETSDK1022 . Para obter informações sobre como resolver o erro, consulte NETSDK1022: itens duplicados foram incluídos.

Utilização implícita de diretivas

A partir do .NET 6, diretivas implícitas global using são adicionadas a novos projetos C#. Isso significa que você pode usar tipos definidos nesses namespaces sem precisar especificar seu nome totalmente qualificado ou adicionar manualmente uma using diretiva. O aspeto implícito refere-se ao fato de que as global using diretivas são adicionadas a um arquivo gerado no diretório obj do projeto.

Diretivas implícitas global using são adicionadas para projetos que usam um dos seguintes SDKs:

  • Microsoft.NET.Sdk
  • Microsoft.NET.Sdk.Web
  • Microsoft.NET.Sdk.Worker
  • Microsoft.NET.Sdk.WindowsDesktop

Uma global using diretiva é adicionada para cada namespace em um conjunto de namespaces padrão baseados no SDK do projeto. Esses namespaces padrão são mostrados na tabela a seguir.

SDK Namespaces padrão
Microsoft.NET.Sdk System
System.Collections.Generic
System.IO
System.Linq
System.Net.Http
System.Threading
System.Threading.Tasks
Microsoft.NET.Sdk.Web Namespaces Microsoft.NET.Sdk
System.Net.Http.Json
Microsoft.AspNetCore.Builder
Microsoft.AspNetCore.Hosting
Microsoft.AspNetCore.Http
Microsoft.AspNetCore.Routing
Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging
Microsoft.NET.Sdk.Trabalhador Namespaces Microsoft.NET.Sdk
Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging
Microsoft.NET.Sdk.WindowsDesktop (Windows Forms) Namespaces Microsoft.NET.Sdk
System.Drawing
System.Windows.Forms
Microsoft.NET.Sdk.WindowsDesktop (WPF) Namespaces Microsoft.NET.Sdk
Removido System.IO
Removido System.Net.Http

Se você quiser desabilitar esse recurso, ou se quiser habilitar diretivas implícitas em um projeto C# existente, você pode fazê-lo global using através da ImplicitUsings propriedade MSBuild.

Você pode especificar diretivas implícitas global using adicionais adicionando Using itens (ou Import itens para projetos do Visual Basic) ao seu arquivo de projeto, por exemplo:

<ItemGroup>
  <Using Include="System.IO.Pipes" />
</ItemGroup>

Referências implícitas de pacotes

Quando seu projeto tem como alvo o .NET Standard 1.0-2.0, o SDK do .NET adiciona referências implícitas a determinados metapacotes. Um metapacote é um pacote baseado em estrutura que consiste apenas em dependências de outros pacotes. Metapacotes são implicitamente referenciados com base nas estruturas de destino especificadas na propriedade TargetFramework ou TargetFrameworks (plural) do seu arquivo de projeto.

<PropertyGroup>
  <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
  <TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
</PropertyGroup>

Se necessário, você pode desabilitar referências implícitas de pacotes usando a propriedade DisableImplicitFrameworkReferences e adicionar referências explícitas apenas às estruturas ou pacotes necessários.

Recomendações:

  • Ao direcionar o .NET Framework ou o NETStandard.Library .NET Standard 1.0-2.0, não adicione uma referência explícita aos metapacotes por meio de um <PackageReference> item no arquivo de projeto. Para projetos do .NET Standard 1.0-2.0, esses metapacotes são implicitamente referenciados. Para projetos do .NET Framework, se qualquer versão do NETStandard.Library for necessária ao usar um pacote NuGet baseado no .NET Standard, o NuGet instalará automaticamente essa versão.
  • Se você precisar de uma versão específica do metapacote ao direcionar o NETStandard.Library .NET Standard 1.0-2.0, poderá usar a <NetStandardImplicitPackageVersion> propriedade e definir a versão necessária.

Criar eventos

Em projetos no estilo SDK, use um destino MSBuild chamado PreBuild ou PostBuild e defina a BeforeTargets propriedade para PreBuild ou a AfterTargets propriedade para PostBuild.

<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="&quot;$(ProjectDir)PreBuildEvent.bat&quot; &quot;$(ProjectDir)..\&quot; &quot;$(ProjectDir)&quot; &quot;$(TargetDir)&quot;" />
</Target>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
   <Exec Command="echo Output written to $(TargetDir)" />
</Target>

Nota

  • Você pode usar qualquer nome para os destinos MSBuild. No entanto, o IDE do Visual Studio reconhece PreBuild e PostBuild direciona, portanto, usando esses nomes, você pode editar os comandos no IDE.
  • As propriedades PreBuildEvent e PostBuildEvent não são recomendadas em projetos no estilo SDK, porque macros como $(ProjectDir) não são resolvidas. Por exemplo, o seguinte código não é suportado:
<PropertyGroup>
  <PreBuildEvent>"$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"</PreBuildEvent>
</PropertyGroup>

Personalizar a compilação

Há várias maneiras de personalizar uma compilação. Talvez você queira substituir uma propriedade passando-a como um argumento para o comando msbuild ou dotnet . Você também pode adicionar a propriedade ao arquivo de projeto ou a um arquivo Directory.Build.props. Para obter uma lista de propriedades úteis para projetos .NET, consulte Referência do MSBuild para projetos do SDK do .NET.

Gorjeta

Uma maneira fácil de criar um novo arquivo Directory.Build.props a partir da linha de comando é usando o comando dotnet new buildprops na raiz do repositório.

Destinos personalizados

Os projetos .NET podem empacotar destinos e propriedades personalizados do MSBuild para uso por projetos que consomem o pacote. Use este tipo de extensibilidade quando quiser:

  • Estenda o processo de compilação.
  • Acesse artefatos do processo de compilação, como arquivos gerados.
  • Inspecione a configuração sob a qual a compilação é invocada.

Você adiciona destinos de compilação personalizados ou propriedades colocando arquivos no formato <package_id>.targets ou <package_id>.props (por exemplo, Contoso.Utility.UsefulStuff.targets) na pasta de compilação do projeto.

O XML a seguir é um trecho de um arquivo .csproj que instrui o comando sobre o dotnet pack que empacotar. O <ItemGroup Label="dotnet pack instructions"> elemento coloca os arquivos de destino na pasta build dentro do pacote. O <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles"> elemento coloca os assemblies e .json arquivos na pasta build .

<Project Sdk="Microsoft.NET.Sdk">

  ...
  <ItemGroup Label="dotnet pack instructions">
    <Content Include="build\*.targets">
      <Pack>true</Pack>
      <PackagePath>build\</PackagePath>
    </Content>
  </ItemGroup>
  <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles">
    <!-- Collect these items inside a target that runs after build but before packaging. -->
    <ItemGroup>
      <Content Include="$(OutputPath)\*.dll;$(OutputPath)\*.json">
        <Pack>true</Pack>
        <PackagePath>build\</PackagePath>
      </Content>
    </ItemGroup>
  </Target>
  ...

</Project>

Para consumir um destino personalizado em seu projeto, adicione um PackageReference elemento que aponte para o pacote e sua versão. Ao contrário das ferramentas, o pacote de destinos personalizados é incluído no fechamento de dependência do projeto consumidor.

Você pode configurar como usar o destino personalizado. Como é um destino MSBuild, ele pode depender de um determinado destino, ser executado após outro destino ou ser invocado manualmente usando o dotnet msbuild -t:<target-name> comando. No entanto, para fornecer uma melhor experiência ao usuário, você pode combinar ferramentas por projeto e destinos personalizados. Nesse cenário, a ferramenta por projeto aceita quaisquer parâmetros necessários e traduz isso na invocação necessária dotnet msbuild que executa o destino. Você pode ver uma amostra desse tipo de sinergia no MVP Summit 2016 Hackathon amostras repo dotnet-packer no projeto.

Consulte também