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.
  • 2631

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

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
                Return (m_name)
            End Get
            Set(ByVal value As String)
                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
                Return (m_arrayNames)
            End Get
            Set(ByVal value As ArrayList)
                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)
            RemotingConfiguration.RegisterWellKnownServiceType(GetType(SimpleInterfaceImpl), "InterfaceImpl",
            Console.WriteLine("Press <enter> to exit.")
            Return (0)
        End Function
    End Class

    Public Class SimpleInterfaceImpl
        Inherits MarshalByRefObject
        Implements ISimpleInterface
        Private arrayNames As New ArrayList()
        Public Sub New()
            Console.WriteLine("SimpleInterfImpl const")
        End Sub

        Default Public ReadOnly Property Item(ByVal index As Integer) As String
                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."
                    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")
            param.ArrayNames = arrayTmp
            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

  ar 2.gif
Listing 25.10: ClientInterface.vb

Shared Function Main(ByVal args As String()) As Integer
    Dim http As HttpChannel = Nothing
    http = New HttpChannel()
    Dim simple As ISimpleInterface = Nothing
    simple = DirectCast(Activator.GetObject(GetType(ISimpleInterface), "http://localhost:1234/InterfaceImpl"),
    Dim arrayParam As New ArrayList()
    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))
    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.


Hope this article would have helped you in understanding Using Objects as Parameters and Return Types in Remoting using VB.NET.


More Articles

© 2020 DotNetHeaven. All rights reserved.