Introducción a la portabilidad de .NET Framework a .NET CoreOverview of porting from .NET Framework to .NET Core

Es posible que tenga código que se ejecuta actualmente en .NET Framework que le interesa portar a .NET Core.You might have code that currently runs on the .NET Framework that you're interested in porting to .NET Core. En este artículo se proporciona:This article provides:

  • Una introducción al proceso de portabilidad.An overview of the porting process.
  • Una lista de las herramientas que puede encontrar de utilidad al portar el código a .NET Core.A list of tools that you may find helpful when you're porting your code to .NET Core.

Introducción al proceso de portabilidadOverview of the porting process

La portabilidad a .NET Core (o .NET Standard) desde .NET Framework es relativamente sencilla para muchos proyectos.Porting to .NET Core (or .NET Standard) from .NET Framework for many projects is relatively straight forward. Hay una serie de cambios necesarios, pero muchos de ellos siguen los patrones descritos a continuación.There are a number of changes that are required, but many of them follow the patterns outlined below. Los proyectos para los que el modelo de aplicación está disponible en .NET Core (por ejemplo, bibliotecas, aplicaciones de consola y aplicaciones de escritorio) suelen requerir pocos cambios.Projects where the app-model is available in .NET Core (such as libraries, console apps, and desktop applications) usually require little changes. Los proyectos que requieren un nuevo modelo de aplicación, como cuando se pasa a ASP.NET Core desde ASP.NET, requieren un poco más de trabajo, pero muchos patrones cuentan con elementos similares que se pueden usar durante la conversión.Projects that require a new app model, such as moving to ASP.NET Core from ASP.NET, require a bit more work, but many patterns have analogs that can be used during the conversion. En este documento se pretende ayudar a identificar las principales estrategias que han empleado los usuarios para convertir correctamente sus bases de código para que tengan como destino .NET Standard o .NET Core. Se aborda la conversión desde dos niveles: en todo el proyecto y solo en un proyecto específico.This document should help with identifying the main strategies that have been employed by users to successfully convert their code bases to target .NET Standard or .NET Core and will address the conversion at two levels: solution-wide and project specific. Vea los vínculos que encontrará en la parte inferior para obtener instrucciones sobre las conversiones específicas de modelos de aplicación.See the links at the bottom for directions on app-model specific conversions.

Le recomendamos que use el proceso que se indica a continuación para portar su proyecto a .NET Core.We recommend you use the following process when porting your project to .NET Core. En cada uno de estos pasos, se presentan los posibles aspectos afectados por los cambios de comportamiento, por lo que debe asegurarse de probar adecuadamente la biblioteca o la aplicación antes de continuar con los pasos posteriores.Each of these steps introduces potential places for behavior changes, so ensure that you adequately test your library or application before continuing on to later steps. Los primeros pasos consisten en preparar el proyecto para un cambio a .NET Standard o .NET Core.The first steps are to get your project ready for a switch to .NET Standard or .NET Core. Si tiene pruebas unitarias, es mejor convertirlas primero para poder seguir probando los cambios en el producto en el que está trabajando.If you have unit tests, it's best to convert them first so that you can continue testing changes in the product you're working on. Dado que portar a .NET Core es un cambio considerable para el código base, se recomienda encarecidamente portar las proyectos de prueba de forma que se puedan ejecutar mientras porta el código.Because porting to .NET Core is such a significant change to your codebase, it's highly recommended to port your test projects so that you can run tests as you port your code over. MSTest, xUnit y NUnit funcionan en .NET Core.MSTest, xUnit, and NUnit all work on .NET Core.

IntroducciónGetting started

En todo el proceso se utilizarán las siguientes herramientas:The following tools will be used throughout the process:

Portabilidad de una soluciónPorting a solution

Cuando una solución contiene varios proyectos, la portabilidad puede parecer más complicada, ya que los proyectos deben abordarse en un orden específico.When there are multiple projects in a solution, the porting can seem more complicated because you must address projects in a specific order. La conversión debe seguir un proceso con orden ascendente, en el que los proyectos sin dependencias de otros proyectos de la solución se conviertan primero y se pase a otros proyectos de la solución después.The conversion process should be a bottom-up approach, where the projects with no dependencies on other projects in the solution are converted first, and continue up through the whole solution.

Para identificar el orden en el que se deben migrar los proyectos, puede usar las siguientes herramientas:In order to identify the order projects should be migrated, you can use the following tools:

  • Los diagramas de dependencia de Visual Studio pueden crear un gráfico dirigido del código en una solución.Dependency Diagrams in Visual Studio can create a directed graph of the code in a solution.
  • Ejecute msbuild _SolutionPath_ /t:GenerateRestoreGraphFile /p:RestoreGraphOutputPath=graph.dg.json para generar un documento JSON que incluya la lista de referencias del proyecto.Run msbuild _SolutionPath_ /t:GenerateRestoreGraphFile /p:RestoreGraphOutputPath=graph.dg.json to generate a json document that includes list of project references.
  • Ejecute el Analizador de portabilidad de .NET con el modificador -r DGML para recuperar un diagrama de dependencias de los ensamblados.Run .NET Portability Analyzer with the -r DGML switch to retrieve a dependency diagram of the assemblies. Para más información, consulte esta página.For more information, see here.

Una vez que tenga la información de dependencias, puede usarla para empezar en los nodos de hoja y subir hasta el árbol de dependencias aplicando los pasos de la sección siguiente.Once you have dependency information, you can use that information to start at the leaf nodes and work your way up the dependency tree applying the steps in the next section.

Pasos por proyectoPer project steps

Le recomendamos que use el siguiente proceso al portar un proyecto a .NET Core:We recommend you use the following process when porting your project to .NET Core:

  1. Convierta todas las dependencias de packages.config en el formato de PackageReference con la herramienta de conversión en Visual Studio.Convert all of your packages.config dependencies to the PackageReference format with the conversion tool in Visual Studio.

    Este paso implica convertir las dependencias del formato packages.config heredado.This step involves converting your dependencies from the legacy packages.config format. packages.config no funciona en .NET Core, por lo que esta conversión es necesaria si tiene dependencias de paquete.packages.config doesn't work on .NET Core, so this conversion is required if you have package dependencies. También requiere las dependencias que está utilizando directamente en un proyecto; esto facilitará los pasos posteriores, ya que reduce la cantidad de dependencias que debe administrar.It also only requires the dependencies you are directly using in a project, which makes later steps easier by reducing the number of dependencies you must manage.

  2. Convierta el archivo de proyecto a la nueva estructura de archivos de estilo SDK.Convert your project file to the new SDK-style files structure. Puede crear nuevos proyectos para .NET Core y copiar los archivos de código fuente, o bien intentar convertir el archivo de proyecto existente usando una herramienta.You can create new projects for .NET Core and copy over source files, or attempt to convert your existing project file with a tool.

    .NET Core usa un formato de archivo de proyecto simplificado y diferente al de .NET Framework..NET Core uses a simplified (and different) project file format than .NET Framework. Deberá convertir los archivos de proyecto en este formato para continuar.You'll need to convert your project files into this format to continue. Este estilo de proyecto también le permite tener como destino .NET Framework, algo interesante en este punto.This project style allows you to also target .NET Framework, which at this point you'll still want to target.

    Puede intentar portar soluciones más pequeñas o proyectos individuales en una operación en el formato de archivo de proyecto de .NET Core con la herramienta dotnet try-convert.You can attempt to port smaller solutions or individual projects in one operation to the .NET Core project file format with the dotnet try-convert tool. No hay ninguna garantía de que dotnet try-convert funcione con todos los proyectos y puede provocar cambios sutiles de comportamiento de los que dependa.dotnet try-convert is not guaranteed to work for all your projects, and it may cause subtle changes in behavior that you depended on. Use esta herramienta como punto inicial que automatice los elementos básicos que se pueden automatizar.Use it as a starting point that automates the basic things that can be automated. No es una solución garantizada para migrar un proyecto, ya que hay muchas diferencias en los destinos que utilizan los proyectos de estilo SDK en comparación con los archivos de proyecto de estilo antiguo.It isn't a guaranteed solution to migrating a project, as there are many differences in the targets used by the SDK style projects compared to the old-style project files.

  3. Redirija todos los proyectos que quiere portar a .NET Framework 4.7.2 o versiones superiores.Retarget all projects you wish to port to target .NET Framework 4.7.2 or higher.

    Este paso garantiza que puede usar alternativas de API para destinos específicos de .NET Framework en los casos donde .NET Core no admite una API determinada.This step ensures that you can use API alternatives for .NET Framework-specific targets when .NET Core doesn't support a particular API.

  4. Actualice todas las dependencias a la versión más reciente.Update all dependencies to the latest version. Es posible que los proyectos estén usando versiones anteriores de bibliotecas que no son compatibles con .NET Standard.Projects may be using older versions of libraries that may not have .NET Standard support. Sin embargo, las versiones posteriores pueden admitirlo con un modificador simple.However, later versions may support it with a simple switch. Esto puede requerir cambios en el código si hay cambios importantes en las bibliotecas.This may require code changes if there are breaking changes in libraries.

  5. Use el Analizador de portabilidad de .NET para analizar los ensamblados y ver si se pueden portar a .NET Core.Use the .NET Portability Analyzer to analyze your assemblies and see if they're portable to .NET Core.

    La herramienta Analizador de portabilidad de .NET analiza los ensamblados compilados y genera un informe.The .NET Portability Analyzer tool analyzes your compiled assemblies and generates a report. Este informe muestra un resumen de portabilidad de alto nivel y un desglose de cada API que está usando y que no está disponible en NET Core.This report shows a high-level portability summary and a breakdown of each API you're using that isn't available on NET Core. Al usar la herramienta, envíe solo el proyecto específico que quiera convertir para centrarse en los cambios de la API que puedan ser necesarios.While using the tool, only submit the individual project you are converting to focus on the API changes that are potentially needed. Muchas de las API tienen una disponibilidad equivalente en .NET Core, por lo que podrá cambiar a estas.Many of the APIs have equivalent availability in .NET Core, which you'll want to switch to.

    Al leer los informes generados por el analizador, la información importante son las API que realmente se usan, y no necesariamente el porcentaje de compatibilidad con la plataforma de destino.While reading the reports generated by the analyzer, the important information is the actual APIs that are being used and not necessarily the percentage of support for the target platform. Muchas API tienen opciones equivalentes en .NET Standard/Core, por lo que comprender los escenarios en los que la biblioteca o la aplicación necesitan la API ayudará a determinar las consecuencias de la portabilidad.Many APIs have equivalent options in .NET Standard/Core, and so understanding the scenarios your library or application needs the API for will help determine the implication for portability.

    Hay algunos casos en los que las API no son equivalentes, por lo que deberá establecer algunas directivas de preprocesador del compilador (es decir, #if NET45) con el objetivo de crear casos especiales para las plataformas.There are some cases where APIs are not equivalent and you'll need to do some compiler preprocessor directives (that is, #if NET45) to special case the platforms. En este punto, el proyecto seguirá teniendo como destino .NET Framework.At this point, your project will still be targeting .NET Framework. Para cada uno de estos casos de destino, se recomienda utilizar condicionales conocidos que se puedan entender como un escenario.For each of these targeted cases, it is recommended to use well-known conditionals that can be understood as a scenario. Por ejemplo, la compatibilidad con AppDomain en .NET Core está limitada, pero, para el escenario de carga y descarga de ensamblados, hay una nueva API que no está disponible en .NET Core.For example, AppDomain support in .NET Core is limited, but for the scenario of loading and unloading assemblies, there is a new API that's not available in .NET Core. Una forma común de controlar esto en el código sería como lo siguiente:A common way to handle this in code would be something like this:

    #if FEATURE_APPDOMAIN_LOADING
    // Code that uses appdomains
    #elif FEATURE_ASSEMBLY_LOAD_CONTEXT
    // Code that uses assembly load context
    #else
    #error Unsupported platform
    #endif
    
  6. Instale el analizador de API de .NET en los proyectos para identificar las API que inician PlatformNotSupportedException en algunas plataformas y otros posibles problemas de compatibilidad.Install the .NET API analyzer into your projects to identify APIs that throw PlatformNotSupportedException on some platforms and some other potential compatibility issues.

    Esta herramienta es similar al analizador de portabilidad, pero en lugar de analizar si el código se pueden basar en .NET Core, analiza si se usa una API de forma que se inicie PlatformNotSupportedException en tiempo de ejecución.This tool is similar to the portability analyzer, but instead of analyzing if code can build on .NET Core, it analyzes whether you're using an API in a way that will throw a PlatformNotSupportedException at run time. Aunque esto no es habitual si va a realizar la portabilidad desde .NET Framework 4.7.2 o superior, es conveniente comprobarlo.Although this isn't common if you're moving from .NET Framework 4.7.2 or higher, it's good to check. Para obtener más información sobre las API que generan excepciones en .NET Core, consulte el artículo.For more information about APIs that throw exceptions on .NET Core, see APIs that always throw exceptions on .NET Core.

  7. En este punto, puede cambiar el destino a .NET Core (generalmente para aplicaciones) o .NET Standard (para bibliotecas).At this point, you can switch to targeting .NET Core (generally for applications) or .NET Standard (for libraries).

    La elección entre .NET Core y .NET Standard depende en gran medida de dónde se ejecutará el proyecto.The choice between .NET Core and .NET Standard is largely dependent on where the project will be run. Si se trata de una biblioteca que usarán otras aplicaciones o se distribuirá a través de NuGet, suele elegirse .NET Standard como destino.If it is a library that will be consumed by other applications or distributed via NuGet, the preference is usually to target .NET Standard. Pero puede haber algunas API que solo estén disponibles en .NET Core por motivos de rendimiento u otras razones. En ese caso, .NET Core debe tener como destino una compilación de .NET Standard disponible, así como un rendimiento o funcionalidad reducidos.However, there may be APIs that are only available on .NET Core for performance or other reasons; if that's the case, .NET Core should be targeted with potentially a .NET Standard build available as well with reduced performance or functionality. Al tener como destino .NET Standard, el proyecto estará listo para ejecutarse en nuevas plataformas (como WebAssembly).By targeting .NET Standard, the project will be ready to run on new platforms (such as WebAssembly). Si el proyecto tiene dependencias en marcos de aplicaciones específicos (como ASP.NET Core), el destino estará limitado por la compatibilidad de las dependencias.If the project has dependencies on specific app frameworks (such as ASP.NET Core), then the target will be limited by what the dependencies support.

    Si no hay ninguna directiva de preprocesador para el código de compilación condicional de .NET Framework o .NET Standard, bastará con encontrar lo siguiente en el archivo de proyecto:If there are no preprocessor directives to conditional compile code for .NET Framework or .NET Standard, this will be as simple as finding the following in the project file:

    <TargetFramework>net472</TargetFramework>
    

    y cambiar al marco que quiera.and switch it to the desired framework. Para .NET Core 3.1, esto sería:For .NET Core 3.1, this would be:

    <TargetFramework>netcoreapp3.1</TargetFramework>
    

    Pero, si se trata de una biblioteca que quiere que siga siendo compatible con compilaciones específicas de .NET Framework, puede tener varios destinos; para ello, sustituya la biblioteca por lo siguiente:However, if this is a library for which you want to continue supporting .NET Framework-specific builds, you can multi-target by replacing it with the following:

    <TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
    

    Si usa las API específicas de Windows (como el acceso al registro), instale el paquete de compatibilidad con Windows.If you're using Windows-specific APIs (such as registry access), install the Windows Compatibility Pack.

Pasos siguientesNext steps