Estrategias de código de portable : #3 Universal Apps | C#
Intermedio
Artículos relacionados
Estrategias de código de portable : #1 PCL - Portable Class Library | C#
Estrategias de código de portable : #2 Código Vinculado | C#
Este es el último artículo de la serie y nos concentraremos en Universal Apps, nuestra tercera estrategia de código portable.
Código fuente de esta serie de artículos
El código fuente completo de esta seria de artículos se encuentra disponible en GitHub, incluye proyectos de Apps con todos los casos expuestos.
https://github.com/JuanKRuiz/Estrategias-de-Codigo-Portable
Universal Apps es en escencia un concepto que define como un mismo conjunto de API's nos permite compartir código a traves de varios dispositivos diferentes aunque su sistema operativo no sea el mismo.
Pero en que se diferencia esto si lo comparamos con Portable Class Libraries ?
Bien en concepto de Universal Apps va más allá.
Proyecto Compartido
En el artículo anterior revisamos la estratégia de código vinculado, lo cual nos permite fácilmente tener códígo en proyecto y hacerlo visible desde un proyecto aparte.
Esta estrategia evoluciona aún más y ahora Visual Studio nos permite crear una solución de Universal Apps.
Una vez creada nos damos cuenta que aparecen tres proyectos:
- Windows 8
- Windows Phone
- Proyecto Compartido
Los proyectos de Windows Phone y WinRT generan cada unos sus propios ensamblados al compilar y adicionalmente comparten la misma API, profundizaremos en esto más adelante.
El proyecto compartido no genera ningún ensamblado, su utilidad es básicamente compartir código. Tal como lo hacemos con los archivos vinculados podemos asumir que todos los archivos que se encuentran en el proyecto compartido están vinculados con el proyecto de WinRT y el de Windows Phone.
Compartir los archivos y tener la misma API nos abre la posibilidad de escenarios donde incluso se comparta hasta el 100% del código fuente y de los archivos, en otras palabras podemos llegar a hacer 2 Apps con el mismo código sin requerir ninguna modificación adicional.
Las secciones o archivos de código que no son comunes se deben dejar en cada preoyecto al que correspondan.
Universal Apps es 100% compatible con las otras estrategias de código portable que hemos visto:
- Librerias Portables
- Patrones de diseño
- Código vinculado
- Clases y métodos parciales
- Compilación condicional
Lenguajes soportados
Universal Apps te permite trabajar Apps con cualquiera de estos lenguajes
* C# / XAML
* HTML / JS
* C++
De arranque esto ya es una diferencia importante, ya que las PCL solo están disponibles para C#.
Compartir archivos de código
Universal Apps nos permite compartir XAML y de paso todos los demás tipos de archivo de acuerdo al tipo de proyecto.
Archivos
- .cs
- .js
- .cpp
- .h
Markup
- .xaml
- .html
- .config
Recursos
- .png
- .jpg
- .resw
- .xml
- etc…
API Universal
Los archivos vínculados desde el folder compartido ofrecen muchas facilidades, sin embargo solo se le puede sacar verdero provecho aumentando al máximo la compatibilidad entre API's, un API Universal nos da hasta un 100% de compatibilidad, aunque en muchos escenarios la compatibilidad efectiva será del 98% apróximadamente.
Porqué?
Porque, por ejemplo hay APIs que solo tienen sentido en Windows Phone por ejemplo:
- Pivot
- AutoSuggestBox
- ContentDialog
- Maps
- System Chrome
- Progress area
- in-call UI
Algunas otras solo tienen sentido en WinRT
- SearchBox
- SettingsFlyout
Nivel de compatibilidad:
Implementación
Ya con esta información nos ponemos en marcha para hacer nuestro ejemplo.
A continuación veremos la versión más simple de programar este requerimiento en cada una de las plataformas:
Código WinRT
//LocalSettingsManager.cs
using System.Diagnostics;
using Windows.Storage;
namespace WinRTApp.Manager
{
public class LocalSettingsManager
{
public void Set(string key, string value)
{
ValidateSecurity();
ApplicationData.Current.LocalSettings.Values[key] = value;
Audit();
}
public void ValidateSecurity()
{
//TODO a lot of things
}
public void Audit()
{
Debug.WriteLine("Parameter Set on WinRT");
//TODO a lot of things
}
}
}
//MainPage.xaml.cs [fragment]
private void Page_Loaded(object sender, RoutedEventArgs e)
{
var lsm = new LocalSettingsManager();
lsm.Set("Last start:", DateTime.Now.ToString());
}
Código Windows Phone
//LocalSettingsManager.cs
using System.Diagnostics;
using System.IO.IsolatedStorage;
namespace WinPhoneApp.Manager
{
public class LocalSettingsManager
{
public void Set(string key, string value)
{
ValidateSecurity();
IsolatedStorageSettings.ApplicationSettings[key] = value;
Audit();
}
public void ValidateSecurity()
{
//TODO a lot of things
}
public void Audit()
{
Debug.WriteLine("Parameter Set on WindowsPhone");
//TODO a lot of things
}
}
}
//MainPage.xaml.cs [fragment]
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
var lsm = new LocalSettingsManager();
lsm.Set("Last start:", DateTime.Now.ToString());
}
Output
Parameter Set on WinRT
Parameter Set on WindowsPhone
Ahora lo convertiremos a Universal Apps, creamos una solución de Universal Apps.
Por defecto el MainPage es creado en cada proyecto
Arrastramos uno de los dos hasta el folder compartido, el otro lo borramos.
Ahora en el proyecto compartido creamos la clase LocalSettingsManager de la siguiente forma (Fíjense en la sección con compilación condicional.):
//LocalSettingsManager.cs
using System.Diagnostics;
using Windows.Storage;
namespace UniversalApp.Manager
{
public partial class LocalSettingsManager
{
public void Set(string key, string value)
{
ValidateSecurity();
ApplicationData.Current.LocalSettings.Values[key] = value;
Audit();
}
public void ValidateSecurity()
{
//TODO a lot of things
}
public void Audit()
{
#if WINDOWS_APP
Debug.WriteLine("Parameter Set on WinRT");
#elif WINDOWS_PHONE_APP
Debug.WriteLine("Parameter Set on Windows Phone");
#endif
//TODO a lot of things
}
}
}
Y modificamos el evento Load del MainPage así
private void Page_Loaded(object sender, RoutedEventArgs e)
{
var lsm = new LocalSettingsManager();
lsm.Set("Last start:", DateTime.Now.ToString());
}
Eso es todo ahora ejecutamos las Apps y este es el resultado
Output
Parameter Set on WinRT
Parameter Set on Windows Phone
Conclusiones
La estrategia de portabilidad con base en Universal Apps permite crear rápidamente y con baja complejidad técnica código portable.
De cierta forma es una evoluación del modelo de código vinculado y el de PCL, ambos al tiempo.
Es mi alternativa de código portable favorita y se la recomiendo a todos. Actualmente el concepto de Universal Apps también ha sido adoptado por Xamarin para crear Apps con iOS para iPhone y iPad constituyéndose en una de las alternativas de portabilidad más poderosas.