Servicios
Imagino que alguna vez habréis tenido que "lidiar" con proyectos de clases portables (PCL). Estas maravillas, cargada de magia y veneno por igual, permite crear código mantenible y altamente reaprovechable, sin embargo, dependiendo de cuanto de portable quieres que sean, el soporte de funciones va escaseando, llegando a limitar cosas tan de uso común como el ToString o algunas funciones LINQ.
Las PCL son de uso muy recurrido cuando usamos el patrón MVVM, ya que reaprovecharemos mucho código entre plataformas, ya sea entre Windows 8 y Windows Phone, o incluso con Android, iPhone y WPF. Esto lo podremos realizar, por ejemplo, mediante el uso de MVVM Cross y Xamarin, poniendo todo el código del ViewModel, Business Layer y Database Layer en clases portables, de forma que tan solo tengamos las vistas, assets y estilos en la capa de la plataforma. Sin embargo, además de las vistas, tendremos algunas funciones que bien por estar trabajando en PCLs, o bien por implementarse de forma diferente en las distintas plataformas no podremos implementar en nuestro ViewModel o incluso en la Business Layer.
Para estos casos lo más práctico es usar servicios. Un servicio no es más que la implementación, en la capa de cada una de las plataformas, de una interfaz que usaremos desde una capa portable.
¿Cómo creo un servicio?
Lo más cómodo es usar algún sistema de inyección de dependencias, en mi caso actualmente uso el IoC que trae Mvvm Cross, pero si usáis otros no variará la forma de implementarlo, tan solo la forma de registralo. Al final de la entrada dejo un enlace a un post de Josué Yeray, con registro de servicios usando Autofac como IoC Container.
Registrando los servicios en MVVM Cross
Capa MVVM - App.cs En la capa de los ViewModels, en el App.cs, creamos un método que nos permita registrar cada uno de los servicios a su interfaz.
public void RegisterType(Type tInterface, Type tService) { Mvx.RegisterType(tInterface, tService); }
Capa de Windows 8 - Setup.cs En el Setup.cs de cada plataforma registramos cada uno de los servicios. En este caso, para simplificar, registramos tan solo el servicio de Notificaciones.
public class Setup : MvxStoreSetup { public Setup(Frame rootFrame) : base(rootFrame){ } protected override IMvxApplication CreateApp() { var app = new Apps.Core.Mvvm.App(); app.RegisterType(typeof(SNotificationService), typeof(INotificationService)); return app; } protected override IMvxTrace CreateDebugTrace() { return new DebugTrace(); } }
Capa de Windows Phone - Setup.cs Más de lo mismo...
public class Setup : MvxPhoneSetup { public Setup(PhoneApplicationFrame rootFrame) : base(rootFrame){ } protected override IMvxApplication CreateApp() { var app = new Apps.Core.Mvvm.App(); app.RegisterType(typeof(SNotificationService), typeof(INotificationService)); return app; } protected override IMvxTrace CreateDebugTrace() { return new DebugTrace(); } }
Y eso es todo, ahora solo queda crear la interfaz y su implementación.
Creamos interfaz
Capa MVVM - INotificationService.cs
public interface INotificationService { /// <summary> /// Mostramos una notificación /// <param name="message">Mensaje que queremos mostrar</param> /// </summary> bool Notify(string message); /// <summary> /// Mostramos una notificación con título /// </summary> /// <param name="message">Mensaje que queremos mostrar</param> /// <param name="title">Título - cabecera de la notificación</param> /// <returns></returns> bool Notify(string message, string title); }
Creamos implementaciones
Capa Plataforma (Windows 8) - SNotificationService.cs
using NotificationsExtensions.ToastContent; using Windows.UI.Notifications; namespace *** public class SNotificationService : INotificationService { IToastNotificationContent toastContent = null; private void ShowToast() { // Create a toast from the Xml, // then create a ToastNotifier object to show the toast ToastNotification toast = toastContent.CreateNotification(); // If you have other applications in your package, //you can specify the AppId of // the app to create a ToastNotifier for that application ToastNotificationManager.CreateToastNotifier().Show(toast); } public bool Notify(string message) { IToastText01 templateContent = ToastContentFactory.CreateToastText01(); templateContent.TextBodyWrap.Text = message; toastContent = templateContent; ShowToast(); return true; } public bool Notify(string message, string title) { IToastText02 templateContent = ToastContentFactory.CreateToastText02(); templateContent.TextHeading.Text = title; templateContent.TextBodyWrap.Text = message; toastContent = templateContent; ShowToast(); return true; } }
Capa Plataforma (Windows Phone) - SNotificationService.cs
using "Project_Name".Resources; using Coding4Fun.Toolkit.Controls; using System.Windows; using System.Windows.Media; namespace *** public class SNotificationService : INotificationService { public bool Notify(string message) { ToastPrompt toast = new ToastPrompt() { Message = message, Background = (SolidColorBrush)Application.Current.Resources["ApplicationPageBackgroundThemeBrush"], Foreground = new SolidColorBrush(Colors.White), TextOrientation = System.Windows.Controls.Orientation.Vertical, TextWrapping = TextWrapping.Wrap }; toast.Show(); return true; } public bool Notify(string message, string title) { ToastPrompt toast = new ToastPrompt() { Title = title, Message = message, Background = (SolidColorBrush)Application.Current.Resources["ApplicationPageBackgroundThemeBrush"], Foreground = new SolidColorBrush(Colors.White), TextOrientation = System.Windows.Controls.Orientation.Vertical, TextWrapping = TextWrapping.Wrap }; toast.Show(); return true; } }
Uso
Tan solo falta llamarlo desde el constructor del ViewModel, IoC ya nos dará la implementación correcta en cada caso.
private INotificationService notificationService; public MyAwesomeViewModel(INotificationService notService)) { this.notificationService = notService; }
Y más adelante, en cualquier método del viewModel.
notificationService.Notify("Service rules", "Awesome");
Y eso es todo... más adelante iré colgando los servicios que más utilizo en Windows 8 y Windows Phone.
Enlaces de interés
Compartiendo codigo en Windows Phone 7 y Windows Phone 8
Estrategias de código portable : #1 PCL - Portable Class Library
Service Locator Pattern in C#: A Simple Example
Using Portable Class Libraries to Reuse Models and ViewModels












