ServerEvents and ClientEvent in Remoting using VB.NET
In this article I will explain you about ServerEvents and ClientEvent in Remoting using VB.NET.
As you learn about Event and Delegates in Remoting using VB.NET in my previous article, now you will see the remaining part:The server creates an HttpChannel to send and receive messages. It registers both server-activated and client-activated SimpleObjects and waits for a client to call a method on the remote object. (See Listing 25.15.)
Listing 25.15: EventServer.vb
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports SimpleEventLib
Namespace EventServer
Class ServerEvent
Private Shared Sub Main(ByVal args As String())
Dim http As HttpChannel = Nothing
http = New HttpChannel(1234)
ChannelServices.RegisterChannel(http)
RemotingConfiguration.RegisterWellKnownServiceType(GetType(SimpleObject), "Simple",
WellKnownObjectMode.Singleton)
RemotingConfiguration.ApplicationName = "Simple"
RemotingConfiguration.RegisterActivatedServiceType(GetType(SimpleObject))
Console.WriteLine("Press <enter> to exit.")
Console.ReadLine()
End Sub
End Class
End Namespace
Notice that the server-activated registration uses Singleton mode. There is no registration of the SyncRemoteEvent object. Running the server executable produces the output in Figure 25.10, while Figure 25.11 displays the client's output.


Listing 25.16: EventClient.vb
Class ClientEvent
Public Sub New()
Console.WriteLine("In ClientEvent constructor")
End Sub
Private Shared Function Main(ByVal args As String()) As Integer
Dim client As SyncRemoteEvent = Nothing
Dim http As HttpChannel = Nothing
http = New HttpChannel(2345)
ChannelServices.RegisterChannel(http)
'client = (SyncRemoteEvent)ClientEvent.InitClientEvent();
client = New SyncRemoteEvent()
Dim simple As SimpleObject = Nothing
simple = DirectCast(Activator.GetObject(GetType(SimpleObject), "http://localhost:1234/Simple"),
SimpleObject)
simple.RemoteEvent += New RemoteEventHandler(client.EventHandler)
Dim ret As String = Nothing
ret = simple.ConCatString("using", "Activator.GetObject")
Console.WriteLine(ret)
simple.RemoteEvent -= New RemoteEventHandler(client.EventHandler)
ret = simple.ConCatString("2 using", "Activator.GetObject")
Console.WriteLine(ret)
Return (0)
End Function
End Class
The client creates a channel, but in this instance it specifies a port number (see Listing 25.16). The server must have a defined port number to contact the client during the event firing. The event handler is created with a simple new; no registration is required. The line commented out above the new operator will be discussed later. SimpleObject is a server-activated object because of the Activator.GetObject(). The code for a client-activated remote object could be Activator.CreateInstance() or as follows:
RemotingConfiguration.RegisterActivatedClientType(GetType(SimpleObject), "http://localhost:1234/Simple")
simple = New SimpleObject()
The client then subscribes to the event and calls SimpleObject.ConcatString() it then unsubscribes and makes a subsequent call to ConcatString().
While experimenting with remote events, we made an interesting discovery. As the code stands now, the event is fired from within the server's application domain to the client's. The client doesn't actually intercept the event unless the server has some reference to it. If, for example, ClientEvent was derived from SyncRemoteEvent, an exception would be thrown when it is registered with SimpleObject's event delegate-that is, unless the remoting framework is tricked into thinking it is dealing with a SyncRemoteEvent rather than a ClientEvent object. Deceiving the framework results in output such as that shown in Figure 25.12.
Figure 25.12: Event Client Output

Listing 25.17: EventClient.cs
Class ClientEvent
Inherits SyncRemoteEvent
Public Sub New()
MyBase.New()
Console.WriteLine("In ClientEvent constructor")
End Sub
Private Shared Function InitClientEvent() As Object
Dim client As SyncRemoteEvent = Nothing
RemotingConfiguration.RegisterWellKnownServiceType(GetType(ClientEvent), "Event",
WellKnownObjectMode.SingleCall)
client = DirectCast(Activator.GetObject(GetType(SyncRemoteEvent), "http://localhost:2345/Event"),
SyncRemoteEvent)
Return DirectCast(client, Object)
End Function
Public Overrides Sub EventHandler(ByVal sender As Object, ByVal args As RemoteArgs)
Console.WriteLine()
Console.WriteLine("In ClientEvent.EventHandler")
Console.WriteLine("Machine:{0} Dir:{1}", args.MachineName, args.CurrentDir)
Console.WriteLine()
MyBase.EventHandler(sender, args)
End Sub
End Class
The first step in accomplishing direct event interception is to make the EventHandler() in SyncRemoteEvent a virtual method. Then, override the method in ClientEvent. Duping the framework takes place in the static method InitClientEvent(). Register the server-activated object as a type of ClientEvent in either SingleCall or Singleton mode. Then, Activator.GetObject() returns a transparent proxy of the requested type, SyncRemoteEvent. If you look at the output, a ClientEvent instance is created, but the proxy has been downcast to a SyncRemoteEvent instance. The result is that the server doesn't have any reference to ClientEvent. No exception is thrown during registration with the event delegate. Because the EventHandler() is virtual, the proper method is called. Experimenting with this as a client-activated object resulted in failure, no matter what twists and contortions were taken.
Conclusion
Hope this article would have helped you in understanding ServerEvents and ClientEvent in Remoting using VB.NET.