Using Objects as Parameters and Return Types in Remoting using VB.NET
In this article I will explain you about Using Objects as Parameters and Return Types in Remoting using VB.NET.
This example is a serveractivated sample, and the client will not be using the new operator, only Activator.GetObject(). The reason for this is to demonstrate the use of interfaces in remoting, and interfaces can't be created. The server has access to the actual implementation, while the client references the interface. Trying to use new or Activator.CreateInstance() on the client results in compiler errors. Because of the use of properties, the server will register the remote objects in Singleton mode. In that manner, the objects are able to maintain state. The example consists of a class library (SimpleInterfaceLib) and two console applications (ClientInterfaceExe and ServerInterfaceExe). Don't forget to add references to System.Runtime.Remoting.dll and SimpleInterfaceLib.dll to the console applications.
You have looked at remote objects only from a marshal-by-reference perspective. Marshal-by-reference classes must inherit from MarsahlByRefObject. In this section we also look at another type of remotable object, marshal by value. Marshal-by-value classes are declared by using the [Serializable] attribute or implementing the System.Runtime.Serialization.ISerializable interface. These objects are copied (serialized) across the wire and are reconstituted at the other end (deserialized). The objects are independent of each other, and modifying one doesn't change the other. The SimpleInterfaceLib code is shown in Listing 25.7.
Listing 25.7: SimpleInterface.vb
Imports System
Imports System.Collections
Namespace SimpleInterfaceLib
Public Interface ISimpleInterface
Default ReadOnly Property Item(ByVal index As Integer) As String
WriteOnly Property Names() As ArrayList
Function InvokeMethod(ByRef param As SimpleParam) As SimpleMarshal
End Interface
End Namespace
The areas of note here are the use of the this and the ref keywords. The this keyword, in this context, is used as an indexer. The ref keyword means that any changes to param in the InvokeMethod will be reflected in the original object. There is also an out keyword, not used here, as a parameter modifier. If we were using the out keyword, in this case, param would be passed in as a null, and the object would be created on the server and assigned to param.
Listing 25.8: SimpleMarshal.vb and SimpleParam.vb
Public Class SimpleMarshal
Inherits MarshalByRefObject
Private m_name As String = Nothing
Public Sub New()
Console.WriteLine("In SimpleMarshal constructor")
End Sub
Public Property Name() As String
Get
Console.WriteLine("SimpleMarshal.Name.get")
Return (m_name)
End Get
Set(ByVal value As String)
Console.WriteLine("SimpleMarshal.Name.set")
m_name = value
End Set
End Property
End Class
<Serializable()> _
Public Class SimpleParam
Private m_arrayNames As ArrayList = Nothing
Public Sub New()
End Sub
Public Property ArrayNames() As ArrayList
Get
Console.WriteLine("SimpleParam.ArrayNames.get")
Return (m_arrayNames)
End Get
Set(ByVal value As ArrayList)
Console.WriteLine("SimpleParam.ArrayNames.set")
m_arrayNames = value
End Set
End Property
In Listing 25.8 the SimpleMarshal class derives from MarshalByRefObject. The SimpleParam class definition uses the [Serializable] attribute. The ISerializable interface could have been used in place of the attribute. Running this code on the server, results in the output shown in Figure 25.8.
Figure 25.8: ServerInterfaceExe Output
Listing 25.9: ServerInterfaceExe.vb
Namespace ServerInterfaceExe
Class ServerInterface
Private Shared Function Main(ByVal args As String()) As Integer
Dim http As HttpChannel = Nothing
http = New HttpChannel(1234)
ChannelServices.RegisterChannel(http)
RemotingConfiguration.RegisterWellKnownServiceType(GetType(SimpleInterfaceImpl), "InterfaceImpl",
WellKnownObjectMode.Singleton)
Console.WriteLine("Press <enter> to exit.")
Console.ReadLine()
Return (0)
End Function
End Class
Public Class SimpleInterfaceImpl
Inherits MarshalByRefObject
Implements ISimpleInterface
Private arrayNames As New ArrayList()
Public Sub New()
MyBase.New()
Console.WriteLine("SimpleInterfImpl const")
End Sub
Default Public ReadOnly Property Item(ByVal index As Integer) As String
Get
Dim ret As String = Nothing
If arrayNames.Count = 0 Then
ret = "No names in list"
ElseIf index >= arrayNames.Count Then
ret = "Index beyond end of list."
Else
ret = DirectCast(arrayNames(index), String)
End If
Console.WriteLine("SimpleInterfImpl indexer")
Return (ret)
End Get
End Property
Public WriteOnly Property Names() As ArrayList
Set(ByVal value As ArrayList)
arrayNames = value
End Set
End Property
Public Function InvokeMethod(ByRef param As SimpleParam) As SimpleMarshal
Dim arrayTmp As New ArrayList()
Dim arrayParam As ArrayList = Nothing
arrayParam = param.ArrayNames
For x As Integer = 0 To arrayParam.Count - 1
arrayTmp.Add(arrayParam(x) + " InvokeMethod")
Next
param.ArrayNames = arrayTmp
Console.WriteLine("SimpleInterfImpl.InvokeMethod()")
Dim paramNew As New SimpleMarshal()
paramNew.Name = "SimplMarshal from MarshalByRefObj"
Return (paramNew)
End Function
End Class
End Namespace
In the main() in Listing 25.9, the code is essentially the same as in our first example. The only changes have been the use of HttpChannel instead of HttpServerChannel and the switch to Singleton mode. HttpChannel combines the functionality of HttpServerChannel and HttpClientChannel. HttpServerChannel receives messages, while HttpClientChannel sends messages. HttpChannel transports messages in either direction.
Just below the main(), the SimpleInterfaceImpl class is defined. It inherits from MarshalByRefObject and ISimpleInterface, by implementing the indexer and Names properties and the InvokeMethod(). When designing remote objects, it is worth considering generic interfaces for their potential reuse.
Figure 25.9: ClientInterfaceExe Output

Listing 25.10: ClientInterface.vb
Private Shared Function Main(ByVal args As String()) As Integer
Dim http As HttpChannel = Nothing
http = New HttpChannel()
ChannelServices.RegisterChannel(http)
Dim simple As ISimpleInterface = Nothing
simple = DirectCast(Activator.GetObject(GetType(ISimpleInterface), "http://localhost:1234/InterfaceImpl"),
ISimpleInterface)
Dim arrayParam As New ArrayList()
arrayParam.Add("Sam")
arrayParam.Add("Tom")
arrayParam.Add("Heidi")
arrayParam.Add("Rose")
arrayParam.Add("Babe")
simple.Names = arrayParam
Dim param1 As SimpleParam = Nothing
param1 = New SimpleParam()
param1.ArrayNames = DirectCast(arrayParam.Clone(), ArrayList)
Dim param2 As SimpleMarshal = Nothing
param2 = simple.InvokeMethod(param1)
Dim arrayRet As ArrayList = Nothing
arrayRet = param1.ArrayNames
For x As Integer = 0 To arrayRet.Count - 1
Console.WriteLine("indexer {0} - ref {1}.", simple(x), arrayRet(x))
Next
Console.WriteLine("SimpleMarshal ""{0}""", param2.Name)
Return (0)
End Function
In Listing 25.10, the param2 returned by InvokeMethod() is a transparent proxy. The client's output is captured in Figure 25.9.
Conclusion
Hope this article would have helped you in understanding Using Objects as Parameters and Return Types in Remoting using VB.NET.