Escuchar eventos entre capas

12/05/2004 - 18:17 por Miguel Arias Fernández | Informe spam
Hola:

He creado un servidor remoto en C# con sus puertos, canales, etc. y un
cliente que se 'engancha' a los objetos que se activan.

Antes de pasar la aplicación a 'remoting' tenía un objeto que lanzaba un
evento que era recogido por el cliente. Ahora en remoting no funciona...
¿alguién sabe como generar un evento en un objeto remoto que puede recogerse
en el cliente?

Un saludo y Gracias, Miguel

Preguntas similare

Leer las respuestas

#1 Angel J. Hernández
16/05/2004 - 15:34 | Informe spam
Saludos...

La manera cmo funciona en Remoting no difiere mucho de la manera
tradicional. Vayamos por paso, el objeto remoto debe derivar de
MarshalByRefObject. Necesitas un delegado (Callback) para poder realizar
disparar el evento, por ejemplo

public delegate void StatusEvent(object sender, StatusEventArgs e)

este reside en el objeto remoto al igual que el evento a consumir digamos...

public event StatusEvent Status;

Todo hasta acá es similar o igual a como se hace sin Remoting. Sin embargo
hay que hacer un tratamiento especial con los argumentos (clase
StatusEventArgs) su declaración es similar a la de cualquier clase de
argumento pero esta ha de estar marcada con el atributo de [Serializable] es
decir...

[Serializable]
public class StatusEventArgs {
private string m_message;

public string Message {
get {return m_message;}
set {m_message = value;}
}

public StatusEventArgs(string m) {
m_message = m;
}
}

Otra nota es... No es posble utilizar objetos SingleCall con eventos, debido
a que el cliente primero registra el manejador de evento y después llama al
método remoto por ende el objeto remoto debe guardar el estado del cliente,
entonces en el archivo de configuración puedes especificar esto...

<configuration>
<system.runtime.remoting>
<application name="miejemplo">
<service>
<activated type="namespace.clase.objetoremoto, objetoremoto"/>
</service>
<channels>
<channel ref = "http" port="4500" />
</channels>
</application>
<system.runtime.remoting>
</configuration>

Necesitas implementar también un EventSink que encapsulará el disparo del
evento...

using System;
using System.Runtime.Remoting.Messaging;

namespace tunamespace {
public class EventSink: MarshalByRefObject {
public EventSink() {}

[OneWay]
public void StatusHandler(object sender, StatusEventArgs e) {
Console.WriteLine("Event Sink: "+e.Message);
}
}
}

Después finalizamos como el cliente, digamos que estamos en el Main()...

RemotingConfiguration.Configure("cliente.exe.config");
EventSink sink = new EventSink();
RemoteObject obj = new RemoteObject();
obj.Status += new StatusEvent(sink.StatusHandler);

Y con esto estamos listo... solo queda establecer unas opciones en la
configuración del archivo del cliente y terminamos...

<configuration>
<system.runtime.remoting>
<application name="cliente">
<client url=http://localhost:4500/miejemplo>
<activated type="namespace.clase.objetoremoto, objetoremoto"/>
</client>
<channels>
<channel ref = "http" port="1000" />
</channels>
</application>
<system.runtime.remoting>
</configuration>

Con eso tenemos...

Saludos y espero te sirva...

Angel J. Hernández M.
MCP

http://groups.msn.com/DesarrolladoresMiranda

"Miguel Arias Fernández" escribió en el mensaje
news:
Hola:

He creado un servidor remoto en C# con sus puertos, canales, etc. y un
cliente que se 'engancha' a los objetos que se activan.

Antes de pasar la aplicación a 'remoting' tenía un objeto que lanzaba un
evento que era recogido por el cliente. Ahora en remoting no funciona...
¿alguién sabe como generar un evento en un objeto remoto que puede


recogerse
en el cliente?

Un saludo y Gracias, Miguel


Respuesta Responder a este mensaje
#2 Miguel Arias Fernández
19/05/2004 - 18:22 | Informe spam
Ante todo muchas gracias.

Con el ejemplo que me has escrito el evento se recoje en el propio objeto y
yo necesitaba que el evento que se produjera en el objeto remoto lo
escuchase el cliente. Con tu permiso lo he modificado un poco

Procedí de la siguiente manera y logré que funcionará, aunque después me
tropecé con un problema que describiré más alante:

Servidor:
RemotingConfiguration.Configure("_RemoteServerHost.exe.config");

Cuyo fichero de configuración es el siguiente:

<?xml version="1.0"?>
<configuration>
<system.runtime.remoting>
<application>
<service>
<activated type="coche.seat,coche"/>
<wellknown type="coche.seat,coche"
mode="Singleton" objectUri="clsseat.soap"/>
</service>
<channels>
<channel ref="http" port="8085">
<serverProviders>
<formatter ref="soap" typeFilterLevel="Full"/>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

El objeto remoto tiene dos clases:
Clase seat:
public delegate void StatusEvent();

public class seat: MarshalByRefObject
{

public event StatusEvent Status;


public seat()
{
m_message= "soy un coche";
}

private string m_message;

public string Message
{
get{return m_message;}
set {m_message = value;}
}

public void Salta(string mensaje)
{
Status();

}
}

Clase Evensink
public class EventSink: MarshalByRefObject
{
public EventSink()
{}

public event StatusEvent Status;


public void Micoche_Status()

{

Status();
}

}

Parte Cliente
RemotingConfiguration.Configure("_Client.exe.config");

cuyo fichero de configurqación es:

<?xml version="1.0"?>
<configuration>
<system.runtime.remoting>
<application>
<client url="http://localhost:8085/">
<activated type="coche.seat,coche"/>
</client>
<channels>
<channel ref="http" useDefaultCredentials="true"
useAuthenticatedConnectionSharing="true" port="0"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>


}


EventSink skin = new EventSink(); <-- llamada local

skin.Status += new StatusEvent(evento);

coche.seat Micoche = new coche.seat();<-- llamada remota

Micoche.Status += new StatusEvent(skin.Micoche_Status);

Micoche.Salta("hola"); <-- salta el evento en el objeto remoto

private void evento() <-- y lo recoge esta función que está en el cliente
{

MessageBox.Show ("Hola");

}


El problema surge cuando en vez de mi servidor remoto hago que el servidor
sea el IIS.

el web.config del IIS es casi el mismo que el del servidor virtual.:
<?xml version="1.0"?>
<configuration>
<system.web>
<customErrors mode="Off"/>
<authentication mode="Windows"/>
<identity impersonate="true"/>
<authorization>
<deny users="?"/>
<allow users="*"/>
</authorization>
</system.web>
<system.runtime.remoting>
<application>
<service>
<activated type="coche.seat,coche"/>
<wellknown type="coche.seat,coche"
mode="Singleton" objectUri="clsseat.rem"/>
</service>
</application>
</system.runtime.remoting>
</configuration>

en el config del cliente solo cambio la nueva ruta.

Pero en el momento que se debería lanzarse el evento se produce el error:

No se puede deserializar el tipo System.DelegateSerializationHolder y los
tipos derivados (como System.DelegateSerializationHolder) en este nivel de
seguridad.

En el IIS tengo activada la autentificacion de windows integrada y
deshabilitado el acceso anónimo.

¿Alguna sugerencia?

Un saludo, Miguel



"Angel J. Hernández" escribió en el mensaje
news:
Saludos...

La manera cmo funciona en Remoting no difiere mucho de la manera
tradicional. Vayamos por paso, el objeto remoto debe derivar de
MarshalByRefObject. Necesitas un delegado (Callback) para poder realizar
disparar el evento, por ejemplo

public delegate void StatusEvent(object sender, StatusEventArgs e)

este reside en el objeto remoto al igual que el evento a consumir


digamos...

public event StatusEvent Status;

Todo hasta acá es similar o igual a como se hace sin Remoting. Sin embargo
hay que hacer un tratamiento especial con los argumentos (clase
StatusEventArgs) su declaración es similar a la de cualquier clase de
argumento pero esta ha de estar marcada con el atributo de [Serializable]


es
decir...

[Serializable]
public class StatusEventArgs {
private string m_message;

public string Message {
get {return m_message;}
set {m_message = value;}
}

public StatusEventArgs(string m) {
m_message = m;
}
}

Otra nota es... No es posble utilizar objetos SingleCall con eventos,


debido
a que el cliente primero registra el manejador de evento y después llama


al
método remoto por ende el objeto remoto debe guardar el estado del


cliente,
entonces en el archivo de configuración puedes especificar esto...

<configuration>
<system.runtime.remoting>
<application name="miejemplo">
<service>
<activated type="namespace.clase.objetoremoto, objetoremoto"/>
</service>
<channels>
<channel ref = "http" port="4500" />
</channels>
</application>
<system.runtime.remoting>
</configuration>

Necesitas implementar también un EventSink que encapsulará el disparo del
evento...

using System;
using System.Runtime.Remoting.Messaging;

namespace tunamespace {
public class EventSink: MarshalByRefObject {
public EventSink() {}

[OneWay]
public void StatusHandler(object sender, StatusEventArgs e) {
Console.WriteLine("Event Sink: "+e.Message);
}
}
}

Después finalizamos como el cliente, digamos que estamos en el Main()...

RemotingConfiguration.Configure("cliente.exe.config");
EventSink sink = new EventSink();
RemoteObject obj = new RemoteObject();
obj.Status += new StatusEvent(sink.StatusHandler);

Y con esto estamos listo... solo queda establecer unas opciones en la
configuración del archivo del cliente y terminamos...

<configuration>
<system.runtime.remoting>
<application name="cliente">
<client url=http://localhost:4500/miejemplo>
<activated type="namespace.clase.objetoremoto,


objetoremoto"/>
</client>
<channels>
<channel ref = "http" port="1000" />
</channels>
</application>
<system.runtime.remoting>
</configuration>

Con eso tenemos...

Saludos y espero te sirva...

Angel J. Hernández M.
MCP

http://groups.msn.com/DesarrolladoresMiranda

"Miguel Arias Fernández" escribió en el mensaje
news:
> Hola:
>
> He creado un servidor remoto en C# con sus puertos, canales, etc. y un
> cliente que se 'engancha' a los objetos que se activan.
>
> Antes de pasar la aplicación a 'remoting' tenía un objeto que lanzaba un
> evento que era recogido por el cliente. Ahora en remoting no funciona...
> ¿alguién sabe como generar un evento en un objeto remoto que puede
recogerse
> en el cliente?
>
> Un saludo y Gracias, Miguel
>
>


email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida