martes, 6 de febrero de 2018
Todos tenemos bibliotecas o componentes escritos para .NET Framework que nos gustaría portar de alguna forma a .NET Core para poder utilizarlos en nuevos proyectos, o, al menos, saber si esto sería posible en un futuro.
Aunque de forma intuitiva muchas veces tenemos la respuesta (sobre todo cuando ésta es un rotundo “no” ;D), sin duda es interesante disponer de información objetiva que indique cómo de lejos estamos de conseguirlo y cuáles son los principales impedimentos.
Para ayudarnos con esta tarea, tenemos a nuestra disposición la herramienta .NET Portability Analyzer, cuyo objetivo es ayudar a detectar APIs usadas por las aplicaciones objeto del análisis que no están disponibles en otras plataformas .NET (Windows, .NET Core, Mono, Xamarin…). También podría utilizarse para comprobar incompatibilidades debidas a breaking changes si hacemos un retarget a una versión distinta del framework .NET.
Tras ello, el analizador generará un informe mostrando la compatibilidad de nuestro proyecto con las plataformas .NET Core 2.0 y .NET Framework 4.7, pero abriendo los settings de la herramienta (en Analyze > Portability Analyzer Settings) podemos especificar tanto el formato de salida -Excel, HTML u otros- como las plataformas que deseamos comprobar expresamente:
De esta forma podremos generar informes muy claros sobre la compatibilidad real del proyecto con los distintos frameworks que hayamos indicado:
El detalle a tener en cuenta es que el hecho de que el 100% de las APIs usadas por nuestra biblioteca estén disponibles en el framework al que queremos portarla no implica que vaya a ejecutarse bien en todos los entornos. Por ejemplo, imaginad una biblioteca para .NET Framework 4.6.1, con un código como el siguiente:
Según este informe, nuestra biblioteca es 100% portable a .NET Framework 4.7.1 y a .NET Core 2.0. En la práctica, indica que este código podríamos compilarlo con el target .NET Framework 4.7.1 sin problema porque no ha aparecido ningún breaking change en el API desde la versión 4.6.1, y también compilaría con éxito para .NET Core 2.0.
Sin embargo, en el informe anterior también veíamos que nuestra biblioteca es compatible sólo en un 94,12% con .NET Standard, e incluso algo más abajo veíamos que los problemas están centrados en el uso de
Si este código lo ejecutamos sobre .NET 4.7.1 o .NET Core 2.0 en Windows, todo funcionará bien porque la implementación de ambos frameworks para este sistema operativo incluye los componentes de acceso al registro.
Pero si el mismo código nos lo llevamos a Linux, compilará también sin problemas; así nos lo había adelantado .NET Portability Analyzer al indicar que es 100% portable a .NET Core, que está disponible en este sistema operativo. Las sorpresas llegarán al ejecutarlo, pues obtendremos una estrepitosa excepción de tipo
Publicado en Variable not found.
Aunque de forma intuitiva muchas veces tenemos la respuesta (sobre todo cuando ésta es un rotundo “no” ;D), sin duda es interesante disponer de información objetiva que indique cómo de lejos estamos de conseguirlo y cuáles son los principales impedimentos.
Para ayudarnos con esta tarea, tenemos a nuestra disposición la herramienta .NET Portability Analyzer, cuyo objetivo es ayudar a detectar APIs usadas por las aplicaciones objeto del análisis que no están disponibles en otras plataformas .NET (Windows, .NET Core, Mono, Xamarin…). También podría utilizarse para comprobar incompatibilidades debidas a breaking changes si hacemos un retarget a una versión distinta del framework .NET.
Nota: en el momento de escribir estas líneas, sólo han sido liberadas versiones “alfa”, lo que quiere decir que esta herramienta se encuentra aún en desarrollo y puede que cambien algunas cosas antes de disponer de la versión final..NET Portability Analyzer se distribuye en dos “sabores” distintos:
- Una aplicación de consola para .NET y .NET Core, desde la cual es posible realizar análisis de aplicaciones desde línea de comandos.
- Una extensión para Visual Studio 2015 y 2017, para hacerlo sin salir del entorno de desarrollo.
Analizar un proyecto
Una vez instalada la extensión desde el propio entorno (podéis buscarla con la denominación “.NET Portability Analyzer”), para analizar la portabilidad de un proyecto bastará con abrir el menú contextual en el explorador de soluciones y buscar la opción “Analyze project portability”. También podemos analizar un ensamblado independiente utilizando el menú “Analyze > Analyze Assembly Portability”.Tras ello, el analizador generará un informe mostrando la compatibilidad de nuestro proyecto con las plataformas .NET Core 2.0 y .NET Framework 4.7, pero abriendo los settings de la herramienta (en Analyze > Portability Analyzer Settings) podemos especificar tanto el formato de salida -Excel, HTML u otros- como las plataformas que deseamos comprobar expresamente:
De esta forma podremos generar informes muy claros sobre la compatibilidad real del proyecto con los distintos frameworks que hayamos indicado:
Y si esta herramienta dice que mi biblioteca es 100% portable a .NET Core, ¿me encontraré algún problema?
Lo que indica el analizador es que no dará errores al compilar y al finalizar tendrás un ensamblado listo para utilizar en tus aplicaciones .NET Core, por lo que no debería aparecer ningún problema a la hora de portar la biblioteca. Hasta ahí, todo bien.El detalle a tener en cuenta es que el hecho de que el 100% de las APIs usadas por nuestra biblioteca estén disponibles en el framework al que queremos portarla no implica que vaya a ejecutarse bien en todos los entornos. Por ejemplo, imaginad una biblioteca para .NET Framework 4.6.1, con un código como el siguiente:
using System;
using Microsoft.Win32;
public class RegistryUtils
{
public static string GetArrowIcon()
{
var icon = (string)Registry.GetValue(
@"HKEY_CURRENT_USER\Control Panel\Cursors", "Arrow", null);
return icon;
}
}
Si realizamos el test de portabilidad a esta biblioteca, el resultado que podríamos obtener sería el siguiente:Según este informe, nuestra biblioteca es 100% portable a .NET Framework 4.7.1 y a .NET Core 2.0. En la práctica, indica que este código podríamos compilarlo con el target .NET Framework 4.7.1 sin problema porque no ha aparecido ningún breaking change en el API desde la versión 4.6.1, y también compilaría con éxito para .NET Core 2.0.
Sin embargo, en el informe anterior también veíamos que nuestra biblioteca es compatible sólo en un 94,12% con .NET Standard, e incluso algo más abajo veíamos que los problemas están centrados en el uso de
System.Win32.Registry
, y es en esta parte donde debemos tener cuidado: el acceso al registro de Windows, como su propio nombre indica, no es multiplataforma.Si este código lo ejecutamos sobre .NET 4.7.1 o .NET Core 2.0 en Windows, todo funcionará bien porque la implementación de ambos frameworks para este sistema operativo incluye los componentes de acceso al registro.
Pero si el mismo código nos lo llevamos a Linux, compilará también sin problemas; así nos lo había adelantado .NET Portability Analyzer al indicar que es 100% portable a .NET Core, que está disponible en este sistema operativo. Las sorpresas llegarán al ejecutarlo, pues obtendremos una estrepitosa excepción de tipo
PlatformNotSupportedException
, porque en este sistema operativo no existe -obviamente- el registro de Windows:jmaguilar@laptop:~/console$ cat Program.cs
using System;
using Microsoft.Win32;
namespace console
{
class Program
{
static void Main(string[] args)
{
var icon = (string)Registry.GetValue(@"HKEY_CURRENT_USER\Control Panel\Cursors", "Arrow", null);
Console.WriteLine("Icon: " + icon);
Console.ReadLine();
}
}
}
jmaguilar@laptop:~/console$ dotnet build
Microsoft(R) Build Engine versión 15.4.8.50001 para .NET Core
Copyright (C) Microsoft Corporation. Todos los derechos reservados.
console -> /home/jmaguilar/console/bin/Debug/netcoreapp2.0/console.dll
Compilación correcta.
0 Advertencia(s)
0 Errores
Tiempo transcurrido: 00:00:02:01
jmaguilar@laptop:~/console$ dotnet run
Unhandled Exception: System.TypeInitializationException:
The type initializer for 'Microsoft.Win32.Registry' threw an exception.
---> System.PlatformNotSupportedException: Registry is not supported on this platform.
at Microsoft.Win32.RegistryKey.OpenBaseKeyCore(RegistryHive hKey, RegistryView view)
at Microsoft.Win32.Registry..cctor()
--- End of inner exception stack trace ---
at Microsoft.Win32.Registry.GetBaseKeyFromKeyName(String keyName, String& subKeyName)
at Microsoft.Win32.Registry.GetValue(String keyName, String valueName, Object defaultValue)
at console.Program.Main(String[] args) in /home/jmaguilar/console/Program.cs:line 10
jmaguilar@laptop:~/console$ _
En conclusión, el hecho de que el Portability Analyzer nos indique que una biblioteca es 100% portable a .NET Core no quiere decir que ésta vaya a ejecutarse correctamente en todos los entornos en los que puede correr dicho framework (Mac, Linux, Windows). Si nuestra intención es que esta biblioteca sea cross-platform, será mejor que nos centremos en conseguir un 100% de portabilidad a .NET Standard, o bien tendremos que introducir en ella código condicional en función de las distintas plataformas a las que nos dirijamos.Publicado en Variable not found.
Aún no hay comentarios, ¡sé el primero!
Enviar un nuevo comentario