Cómo reutilizar el código de una biblioteca de clases .NET desde una aplicación Silverlight
Existe cierta confusión con la compatibilidad entre binarios de Silverlight y binarios de .NET, y a más de uno le pilla por sorpresa que en un proyecto de Visual Studio de una aplicación Silverlight, no se pueden referenciar bibliotecas de clases (class library) desarrolladas en .NET de escritorio (para diferenciarlo del .NET de Silverlight). El motivo es que el runtime y la biblioteca de clases de .NET para Silverlight es un subconjunto del runtime y la biblioteca de clases de .NET de escritorio, y por lo tanto no son directamente compatibles.
Se puede migrar el código de las clases .NET a clases .NET para Silverlight, y en ocasiones puede ser tan sencillo como recompilar el mismo código fuente (por ejemplo, como una Silverlight Class Library). En otras ocasiones esta migración no es directa, dado que la biblioteca de clases de Silverlight no contiene todas las clases que la biblioteca de clases del Framework .NET.
.NET Framework Class Library
https://msdn.microsoft.com/en-us/library/ms229335.aspx
.NET Framework Class Library for Silverlight
https://msdn.microsoft.com/en-us/library/cc838194.aspx
Supongamos que queremos reutilizar unas bibliotecas de clases que manejan objetos DataSet, y dado que .NET para Silverlight (hasta la versión Silverlight 4 RC) no contiene el namespace System.Data, no podemos simplemente recompilar el código fuente (fallaría la compilación dado que no estarían implementada ninguna clase DataSet).
Una posible implementación que nos permite reutilizar al máximo nuestras bibliotecas de clases .NET desde aplicaciones Silverlight sería implementar una interfaz, expuesta como un web service, y consumir dicho web service desde la aplicación Silverlight.
De esta manera, todo el código de .NET de escritorio se ejecutará en el servidor web, y la aplicación Silverlight que se ejecutará en el navegador del cliente únicamente representará la capa de presentación.
Os muestro un pequeño ejemplo en C# como prueba de concepto. En este ejemplo, el web service está implementado como un web service de ASP.NET 2.0 (*.asmx), pero considerad la posibilidad de implementarlo como un web service WCF (Windows Communication Foundation), que es la siguiente generación de web services de .NET.
Supongamos que tenemos la siguiente clase en nuestra biblioteca de lógica de negocio. Esta es la clase cuyo código nos gustaría reutilizar en Silverlight, pero dado que hace uso de System.Data no podemos recompilar el código sin más.
using System;
using System.Data;
namespace SilverlightTest.Web
{
public class BusinessLogic
{
public DataSet getCustomerData(int customerID)
{
DataSet dataSet = new DataSet();
DataTable dataTable = new DataTable();
dataTable.Columns.Add("Columna 1");
dataTable.Columns.Add("Columna 2");
dataTable.Rows.Add(new object[] { "celda 0-0", "celda 0-1" });
dataTable.Rows.Add(new object[] { "celda 1-0", "celda 1-1" });
dataTable.Rows.Add(new object[] { "celda 2-0", "celda 2-1" });
dataTable.Rows.Add(new object[] { "celda 3-0", "celda 3-1" });
dataSet.Tables.Add(dataTable);
return dataSet;
}
}
}
Para solventar este problema, podemos crear un web service que exponga el método getCustomerData. En este caso, para hacerlo compatible con Silverlight, convertiremos el objeto DataSet en uno o varios arrays bidimensionales (uno por cada DataTable del DataSet) antes de enviar la respuesta al cliente Silverlight:
using System;
using System.Data;
using System.Web;
using System.Web.Services;
using SilverlightTest.Web;
[WebService]
public class SilverlightInterface : System.Web.Services.WebService
{
[WebMethod]
public object[][] getCustomerData(int customerID)
{
//Utilizamos la lógica de la biblioteca de clases de .NET de escritorio
BusinessLogic businessLogic = new BusinessLogic();
DataSet dataSet = businessLogic.getCustomerData(customerID);
int x = dataSet.Tables[0].Rows.Count;
int y = dataSet.Tables[0].Columns.Count;
//Declaramos y demensionamos el Array
object[][] dataArray = new object[x][];
for (int i = 0; i < x; i++)
{
dataArray[i] = new object[y];
}
//Rellenamos el Array con los datos del DataSet
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
dataArray[i][j] = dataSet.Tables[0].Rows[i][j];
}
}
return dataArray;
}
}
Por último, desde el cliente Silverlight consumimos el web service de la siguiente manera tras haber incluido la referencia web (que hemos llamado BusinessLogicWS):
public partial class SilverlightPage : UserControl
{
public SilverlightPage()
{
InitializeComponent();
//Creamos el objeto proxy para interactuar con el web service
BusinessLogicWS.SilverlightInterfaceSoapClient wsProxy =
new BusinessLogicWS.SilverlightInterfaceSoapClient();
wsProxy.getCustomerDataCompleted
+= new EventHandler
<BusinessLogicWS.getCustomerDataCompletedEventArgs>
(getCustomerDataCompletedHandler);
int CustomerID = 1234;
//Realizamos la llamada asíncrona al web service
wsProxy.getCustomerDataAsync(CustomerID);
}
void getCustomerDataCompletedHandler(object sender,
BusinessLogicWS.getCustomerDataCompletedEventArgs e)
{
//Obtenemos los datos de la respuesta del web service
ObservableCollection<SilverlightTest.BusinessLogicWS.ArrayOfAnyType>
data = e.Result;
//Hacemos algo con esos datos
for (int i=0; i<data.Count; i++)
{
for (int j = 0; j < data[i].Count; j++ )
{
Debug.WriteLine(data[i][j].ToString());
}
}
}
}
De esta forma, hemos construido una interfaz entre la aplicación Silverlight y nuestra biblioteca de clases .NET, pudiendo reutilizar el código de las bibliotecas de clases .NET y solventando los problemas de incompatibilidades entre tipos de datos.
Hasta el próximo post,
- Daniel Mossberg
Comments
Anonymous
April 23, 2010
Hola, tengo una duda, en esta parte nose como hacelor ObservableCollection<SilverlightTest.BusinessLogicWS.ArrayOfAnyType> data = e.Result; En particular esta parte: SilverlightTest.BusinessLogicWS.ArrayOfAnyType yo tengo mi referencia algo asi como esta: using SilverDemo02.WS2005; no me muestra de ninguna forma la propiedada ArrayOfAnyType que me falta???Anonymous
September 30, 2012
Hola a mi tampoco me sale esa clase ArrayOfAnyType me quedo hasta ObservableCollection< y de ahí no logro sacar esa clase no he encontrado nada por favor podrias ayudarme mi referencia esta como SolicitudConexion.Referencia1