.NET Framework e .NET Core, o que muda?
Basicamente o .NET Framework, que nasceu lá em 2001, foi criado para rodar em cima do Windows, e é isto que vem acontecendo desde então, até a versão 4.8, que encerrará este ciclo.
Há cerca de cinco anos, a Microsoft resolveu recriar o .NET, com uma arquitetura totalmente nova, multiplataforma, ou seja, rompendo a barreira do Windows, e abrindo espaço para executarmos o nosso código .NET em Linux e Mac OS!
Agora podemos escrever um código em C#, por exemplo, que roda em todas as plataformas, ou seja, o mesmo código, sem nenhuma mudança!
Criando um projeto em .NET Framework
Nesse exemplo, vamos criar um simples projeto em .NET, que será a base da nossa conversão.
Vamos colocar um acesso a dados com Dapper, que é um MicroORM, acessando o banco de dados Northwind da Microsoft .
Podemos adicionar o Dapper usando o Manage Nuget Package.
O banco Northwind possui uma tabela Customers, e iremos criar uma classe com este mesmo nome para acessar os dados (vou usar somente alguns campos):
public class Customers
{
public string CustomerID { get; set; }
public string CompanyName { get; set; }
public string City { get; set; }
}
E depois vamos incluir um pequeno código para listar os clientes:
using System;
using System.Data.SqlClient;
using Dapper;
namespace ProjetoNetFull
{
class Program
{
static void Main(string[] args)
{
var conexao = new SqlConnection("data source=(local); initial
catalog=northwind; integrated security=true;");
var dados = conexao.Query(
"select CustomerID, CompanyName, City from Customers");
foreach(var c in dados)
{
Console.WriteLine($"{c.CustomerID} - {c.CompanyName} - {c.City}");
}
}
}
}
Basicamente criamos uma conexão e através do Dapper (para efeito de demonstração deixei a string direto no código, mas coloque em um arquivo externo no seu projeto), usamos o comando "Query" para serializar o resultado da consulta em uma coleção de objetos "Customer", que depois serão impressos na tela.
O grande ponto aqui são os itens que este projeto contém:
- Componente de terceiro (Dapper)
- Arquivos que compõe o projeto, ou seja, nossas classes
- O próprio arquivo do projeto: .csproj
Verificando a compatibilidade do projeto
Antes de converter o projeto, precisamos ver se o nosso código não está muito "amarrado" ao Windows usando a ferramenta .NET Portability Analyzer. Ela irá verificar o nosso código e informar se ele é compatível com o .NET Core, através de uma planilha de Excel:
Esta ferramenta analisa o assembly e não o código fonte, basta apontar para o nosso diretório bin\debug (ou bin\release) e indicar o arquivo do projeto, que neste caso é "ProjetoNetFull.exe"
Depois de executado, teremos uma planilha com 3 sub-planilhas: "Portability Summary", "Details" e "Missing assemblies":
Portability Summary:
Temos aqui o resultado geral, indicando a compatibilidade ou não com o .Net Core e .Net Standard. No nosso caso, "tudo verde", indicando que podemos migrar, mas antes vamos olhar o "Details"
"Details"
Nesta parte temos os tipos de dados e a compatibilidade:
No nosso exemplo, foi indicado que usamos "SqlConnection" e que este tipo é suportado pelo .NET Standard, mas podemos ter tipos não suportados onde precisamos migrar o componente, ou reescrever o código:
Missing Assemblies:
Esta parte mostra arquivos que estão referenciados no binário analisado e que não foram encontrados. Assim você precisa rodar a ferramenta em cada um deles, ou ver se já existe uma versão específica para o .NET Core.
Meu projeto deu incompatível, o que fazer?
Se o seu projeto apresentou muitas incompatibilidades(amarelo ou vermelho), existem algumas opções:
- Veja se é possível migrar o componente incompatível, talvez exista uma versão dele para .NET Core;
- Busque uma alternativa ao componente;
- Veja se é possível reescrever esta parte do código;
- Se o trabalho for muito grande para migrar ou reescrever o código, considere os benefícios da migração, caso não faça sentido, mantenha o código no .NET Framework e trabalhe algumas partes de maneira híbrida (eu falei sobre isto no evento .NET Conf com o título "Why you should create your next library using .NET Standard");
Entendendo o novo formato de projeto - SDK Project
Uma das grandes mudanças em projetos .NET Core é o formato do arquivo do projeto, ou seja, o .CSPROJ, que agora está em um formato chamado SDK Project.
Este novo formato de projeto é muitos mais simples de entender, veja:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
Este arquivo indica basicamente que o projeto produz um arquivo "Exe" e está usando o .NET Core 3.0.
Olhando o arquivo atual do projeto temos:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A0D64988-CAB7-452F-ACC7-B7F84BDA6B3A}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ProjetoNetFull</RootNamespace>
<AssemblyName>ProjetoNetFull</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dapper, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Dapper.2.0.30\lib\net461\Dapper.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Customers.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
Acho que ficou claro como o arquivo foi simplificado!
Configurando o projeto .NET Core
A primeira diferença entre os projetos é que os pacotes agora foram incorporados ao arquivo .csproj e o arquivo packages.config não existe mais. Então vamos iniciar a migração por este arquivo através da função "Migrate packages.config to PackageReference":
Esta opção abre uma janela mostrando os pacotes e ao clicar em OK, remove o arquivo packages.config e copia seu conteúdo para uma seção "ItemGroup" do seu arquivo .csproj.
Agora vamos editar o arquivo .csproj (não esqueça do "Unload Project").
Neste arquivo precisamos copiar apenas a seção que foi migrada do packages.config, que está em um "ItemGroup" com um "PackageReference":
<ItemGroup>
<PackageReference Include="Dapper">
<Version>2.0.30</Version>
</PackageReference>
</ItemGroup>
Agora podemos apagar completamente o arquivo, mas salvando o texto anterior no bloco de notas.
Com o arquivo totalmente em branco, vamos copiar o nosso modelo de SDK Project, incluindo o PackageReference, que resultará no seguinte arquivo:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper">
<Version>2.0.30</Version>
</PackageReference>
</ItemGroup>
</Project>
Um detalhe importante é que o arquivo AssemblyInfo.cs foi incorporado ao .csproj, então precisamos apagá-lo e migrar as informações para o arquivo de projeto:
]<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<Company>CDS Software</Company>
<Authors>Carlos dos Santos</Authors>
<PackageId>ProjetoNetFull</PackageId>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<Copyright>Copyright © 2019 Carlos dos Santos</Copyright>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper">
<Version>2.0.30</Version>
</PackageReference>
</ItemGroup>
</Project>
Pronto, agora temos um arquivo de projeto convertido para .NET Core (recarregue o projeto com a opção "Reload Project").
Agora temos um projeto convertido para .NET Core, veja:
Talvez você precise fazer o upgrade dos seus pacotes para .NET Core, se isto for necessário, abra o gerenciador de pacotes do Nuget e atualize os pacotes, ou reinstale a versão compatível. No nosso exemplo o Dapper já é compatível com o .NET Core, mas precisamos instalar a nova versão do System.Data.SqlClient:
Compilando e testando
Agora basta compilar e testar o seu projeto. Uma mudança que você irá notar é que os binários não ficam mais na pasta bin\debug ou bin\release, mas em uma subpasta de acordo com a versão do .NET Core. No nosso exemplo usamos o .NET Core 3.0 então teremos a seguinte estrutura:
ProjetoNetFull\bin\Debug\netcoreapp3.0
E dentro dela os binários!
Dá para simplificar um pouco ?
A Microsoft lançou um projeto no GitHub que ajuda na conversão de um projeto .NET para o formato SDK Project. Isto simplifica bastante a conversão!
Conclusão
Tomando alguns cuidados e analisando corretamente seu projeto, é possível migrar uma estrutura em .NET Framework para .NET Core com o auxílio de ferramentas do próprio Visual Studio e começar a aproveitar os grandes benefícios desta plataforma.
Sobre o autor
Carlos dos Santos, é responsável pela área de inovação da CDS Informática, trabalha com desenvolvimento de software há mais de 20 anos, possui diversas certificações Microsoft, além de fazer parte do programa Microsoft MVP desde 2008 e do programa Microsoft Regional Director desde 2017. É palestrante em diversos eventos no Brasil e exterior, e mantém um blog com diversos assuntos relatios a tecnologia em www.carloscds.net