Creando Clientes Remoting

Fecha: 13/Jul/2005 (7 de Julio de 2005)
Autor: Bruno Capuano; bcapuano@gmail.com

 


Introducción

Usualmente cuando utilizamos componentes y los publicamos con Remoting, se dificulta mantener una configuración coherente de las partes del sistema. He visto lugares donde se utiliza un archivo Remoting.Config para guardar la configuración de los componentes, y luego dentro de otro archivo .config, se guarda casi el mismo dato para poder usarlo desde la aplicación.

Remoting

Una de las técnicas aconsejadas por Microsoft y que por lo general da muy buen resultado, es guardar la configuración en un único archivo .Config (Remoting.Config por ejemplo) y al momento de inicializar la aplicación cargar dinámicamente esta configuración. En el caso de una aplicación Windows, a esto lo podemos hacer en el evento Load del Form de la siguiente manera :

Private Sub frmPrincipal_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

  ' carga la configuracion de los componentes de Remoting

  Dim remFile As String = "Remoting.config"

  System.Runtime.Remoting.RemotingConfiguration.Configure(remFile)

End Sub

El archivo Remoting.Config podría contener la siguiente información

<configuration>

  <system.runtime.remoting >

  <application>

  <channels>

    <channel ref="http" useDefaultCredentials='true'>

    <clientProviders>

      <formatter ref="binary"></formatter>

    </clientProviders>

    </channel>

  </channels>

  <client>

    <wellknown type="ICliente, ICliente" url="http://localhost/ServidorComponentes/Cliente.soap"></wellknown>

  </client>

  </application>

  </system.runtime.remoting>

</configuration>

Cuando se desea crear una nueva instancia de un componente, por lo general necesitamos conocer el tipo de objeto que queremos probar y la url donde se publica el mismo. Usualmente se utiliza el objeto Activator y las líneas para inicializar un componente de Remoting son:

Dim urlRem As String

Dim iC As ICliente

urlRem = "http://localhost/ServidorComponentes/Cliente.soap"

iC = Activator.GetObject(GetType(ICliente), urlRem)

Sin embargo, si ya tenemos cargada la información desde el archivo .config, se puede acelerar el proceso de creación de componentes, leyendo la información desde el registro local de componentes de Remoting . Para esto podemos utilizar el método RemotingConfiguration.GetRegisteredWellKnownClientTypes

RemotingConfiguration.GetRegisteredWellKnownClientTypes (Método) 
Recupera una matriz de tipos de objetos registrados en el cliente como tipos conocidos.
[Visual Basic]
Public Shared Function GetRegisteredWellKnownClientTypes() As WellKnownClientTypeEntry()
Valor devuelto
Matriz de tipos de objetos registrados en el cliente como tipos conocidos.
Comentarios
Los tipos de objetos conocidos pueden ser llamadas únicas o singleton. Si un tipo de objeto es una llamada única, se crea una nueva instancia de él cada vez que se recibe una llamada del cliente. Todas las llamadas a un objeto singleton se controlan mediante una instancia de ese objeto.

Utilizando este método, podemos crear un helper, que cargue internamente una lista de los objetos que estan configurados y luego, permita de una manera las simple, crear los objetos Remoting. Para esto creamos una clase Helper. 

Imports System.Runtime

Imports System.Runtime.Remoting

 Public Class RemotingHelper

''' -----------------------------------------------------------------------------

''' <summary>

''' Define si se ha inicializado el diccionario shared que almacena los tipos

''' que se pueden acceder desde remoting

''' </summary>

''' <remarks>

''' </remarks>

''' <history>

''' [BCA] 27/06/2005 Created

''' </history>

''' -----------------------------------------------------------------------------

Public Shared mLoaded As Boolean

''' -----------------------------------------------------------------------------

''' <summary>

''' Almacena los tipos que se pueden acceder desde Remoting

''' </summary>

''' <remarks>

''' </remarks>

''' <history>

''' [BCA] 27/06/2005 Created

''' </history>

''' -----------------------------------------------------------------------------

Public Shared mWellKnownTypes As IDictionary

''' -----------------------------------------------------------------------------

''' <summary>

''' Retorna un objecto, a partir del tipo del mismo. Se crea en base a la

''' definicion de los objetos que se pueden crear remotos

''' </summary>

''' <param name="type">Tipo del Objeto a crear</param>

''' <returns>New Object</returns>

''' <remarks>

''' </remarks>

''' <history>

''' [BCA] 27/06/2005 Created

''' </history>

''' -----------------------------------------------------------------------------

Public Shared Function GetObject(ByVal type As Type) As Object

Dim strExc As String

' inicializa el cache de objetos

If Not mLoaded Then

LoadRemTypes()

End If

' obtiene el tip

Dim entr As WellKnownClientTypeEntry = mwellKnownTypes(type)

If entr Is Nothing Then

strExc = "Type [{0}] not found!"

strExc = String.Format(strExc, type.ToString)

Throw New RemotingException(strExc)

End If

' crea el objeto

Return Activator.GetObject(entr.ObjectType, entr.ObjectUrl)

End Function

''' -----------------------------------------------------------------------------

''' <summary>

''' Inicializa el diccionario interno de Objetos que se pueden crear por remoting

''' </summary>

''' <remarks>

''' </remarks>

''' <history>

''' [BCA] 27/06/2005 Created

''' </history>

''' -----------------------------------------------------------------------------

Public Shared Sub LoadRemTypes()

Dim sExcepcion As String = ""

Dim sAssName As String

mLoaded = True

mwellKnownTypes = New Hashtable

' recorre los tipos que se pueden crear

For Each entr As WellKnownClientTypeEntry In RemotingConfiguration.GetRegisteredWellKnownClientTypes()

If (entr.ObjectType Is Nothing) Then

Try

sAssName = entr.AssemblyName

Catch

sAssName = "No Assembly Name defined."

End Try

sExcepcion = "A configured type could not be found. Please check spelling. AssemblyName: [{0}]"

sExcepcion = String.Format(sExcepcion, sAssName)

Throw New RemotingException(sExcepcion)

End If

' agrega el nuevo tipo

mwellKnownTypes.Add(entr.ObjectType, entr)

Next

End Sub

End Class

Finalmente la creación de un objeto a partir de un servidor de componentes Remoting, queda mucho mas simple

Dim iC As ICliente

iC = RemotingHelper.GetObject(GetType(ICliente))

Pues bien, este es un pequeño ejemplo de algo que también nos ayuda a programar de una forma mas simple.

Si quieren que se incluya en .Net 2.0 , lo pueden votar en http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=d85ff541-59d9-4b9e-a6af-76eab9489f8e.

Ante cualquier duda, pueden escribirme a  bcapuano@gmail.com

Saludos

El Bruno

http://spaces.msn.com/members/brunocapuano.


Espacios de nombres usados en el código de este artículo:

System.
System.Runtime
System.Runtime.Remoting



ir al índice