Configuração de Projetos Multi-Targeting no Ecossistema .NET

No desenvolvimento de bibliotecas .NET, é comum a necessidade de oferecer suporte a múltiplas versões do framework, permitindo que o mesmo código seja consumido tanto por aplicações legadas em .NET Framework quanto por aplicações modernas em .NET Core ou .NET 5+.

1. Configuração do Projeto para Múltiplos Alvos

Para habilitar o suporte a múltiplas plataformas, o primeiro passo consiste em modificar o arquivo de projeto (.csproj). Em vez de utilizar a tag snigular <TargetFramework>, devemos utilizar a versão plural <TargetFrameworks>, separando as versões por ponto e vírgula.

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

  <PropertyGroup>
    <!-- Define o suporte para .NET Framework 4.7.2 e .NET 6.0 -->
    <TargetFrameworks>net472;net6.0</TargetFrameworks>
  </PropertyGroup>

</Project>

Após essa alteração, ao recarregar o projeto, o Visual Studio passará a compilar a solução para ambos os ambientes simultaneamente.

2. Gerenciamento de Referências Condicionais

Diferentes frameworks possuem APIs distintas. Por exemplo, bibliotecas como System.Web são nativas do .NET Framework, enquanto no .NET modernizado, funcionalidades equivalentes podem exigir paccotes NuGet específicos ou estar localizadas em namespaces diferentes.

Referências de Sistema

Para referenciar assemblies que existem apenas em uma plataforma específica, utilizamos condições no MSBuild:

<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
  <Reference Include="System.Web" />
</ItemGroup>

Referências de Pacotes NuGet

Caso precise de uma biblioteca que mudou de estrutura, como o processamento de imagens (System.Drawing.Common), a configuração deve garantir a versão correta para cada runtime:

<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
  <PackageReference Include="System.Drawing.Common" Version="6.0.0" />
</ItemGroup>

3. Implementação de Código Cross-Platform

Ao consumir a biblioteca em diferentes tipos de projetos, podemos testar a compatibilidade instanciando classes que lidam com provedores de nuvem ou manipulação de arquivos. Abaixo, um exemplo de como estruturar uma chamada de download que se comporta de forma consistente entre os runtimes:

public class GerenciadorDeArquivos
{
    public void ExecutarDownload(string bucket, string remotePath, string localPath)
    {
        var provider = new CloudStorageProvider();
        provider.DownloadObject(bucket, remotePath, localPath);
        Console.WriteLine($"Download concluído no ambiente: {AppDomain.CurrentDomain.FriendlyName}");
    }
}

// Exemplo de uso em aplicação console
static void Main(string[] args)
{
    var gestor = new GerenciadorDeArquivos();
    
    #if NET472
        gestor.ExecutarDownload("meu-bucket", "dados.zip", @"C:\temp\framework_dados.zip");
    #else
        gestor.ExecutarDownload("meu-bucket", "dados.zip", "/home/user/core_dados.zip");
    #endif
}

4. Resolução de Dependências na Compilação

Em alguns cenários com .NET Core ou .NET Standard, as dependências de pacotes NuGet podem não ser copiadas automaticamente para a pasta de saída (bin). Para forçar a inclusão de todos os assemblies necessários, adicione a seguinte propriedade ao .csproj:

<PropertyGroup>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>

5. Empacotamento e Distribuição

Para gerar um pacote NuGet que cotnenha todas as versões compiladas, utilize o comando de empacotamento do .NET CLI. Isso criará um arquivo .nupkg contendo as pastas de lib para cada framework configurado.

# Executa o pack em modo Release e define o diretório de saída
dotnet pack -c Release -o ./dist/pacotes

Se o seu projeto consome outros projetos locais, certifique-se de configurar a saída dos assets no arquivo de projeto principal para garantir que os arquivos .dll sejam incluídos corretamente no pacote final:

<ItemGroup>
  <ProjectReference Include="..\MinhaLib.Core\MinhaLib.Core.csproj">
    <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
    <IncludeAssets>all</IncludeAssets>
  </ProjectReference>
</ItemGroup>

Tags: .NET .NET Framework .NET Core MSBuild NuGet

Publicado em 11-1 02:13