Home All Groups Group Topic Archive Search About

Remoting Server Object not passing properties

Author
15 Feb 2006 6:24 PM
Denny
I have noticed this weird behavior and wondered if anyone else has seen this or knows a solution. I have this class that inherits from NameObjectCollectionBase that has one public property (name):



Private _name As String

Public Property Name() As String

   Get

     Return _name

   End Get

   Set(ByVal value As String)

     _name = value

   End Set

End Property

Public Sub New()



End Sub

Protected Sub New(ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext)

        MyBase.New(info, context)

End Sub



The server object creates, sets the name property and returns it



From the server:



Inherits MarshalByRefObject

Implements IEmployee.IEmployee



Public Function GetEmployee() As Employee.Employee Implements IEmployee.IEmployee.GetEmployee

        Dim TestEmployee As New Employee.Employee

        TestEmployee.Name = "Harry"

        Return TestEmployee

End Function



From the client:



ServerEmployee = DirectCast(Activator.GetObject(GetType(IEmployee.IEmployee), URL.ToString), IEmployee.IEmployee)



Dim Employee As New Employee.Employee

Employee = ServerEmployee.GetEmployee



The problem is when the client recieves the object, its name property = "". I have double checked this and when the object is created on the server, the property is set. I have tried it with other collections and it works as expected, the problem seems to be any classes that derive from Collections.Specialized namespace. All of the base properties retain settings. Only properties in the inherited class seem not to retain their settings.



Does anyone see something I am missing?



Thanks.




--
DENNY BROWNE

Author
16 Feb 2006 9:25 AM
Steven Cheng[MSFT]
Hi Denny,

Welcome to the MSDN newsgroup.

From your description, I understand you have developed a custom class which
derives from "NameObjectCollectionBase" class. The class also has a custom
string property named "Name". In your .net remoting application, you use a
server object to return an instance of this custom class to client-side.
However, you found that the returned custom class instance always have
empty "Name" value, correct?

Based on the code snippet you provided, I've also done some tests by
creating a simple custom class inheriting from NameObjectCollectionBase and
I did encounter the problem you mentioned.  After doing some further
research, I found that the problem is caused by the base class
"NameObjectCollectionBase". Since "NameObjectCollectionBase" class has
implemented the "ISerializable" interface, when the .net runtime
serializing the custom class instance, it will call the "GetObjectData"
method of the "NameObjectCollectionBase" class. However,
"NameObjectCollectionBase" class's  "GetObjectData" method only save its
own properties, so our sub class's property values are lost.  To resolve
this problem, we need to explicitly override the
"ISerializable.GetObjectData" method to store our own class's property(if
you want to persist it). In addition, we also need to retrieve the data
back from the SerializationInfo collection in the deserialization
constructor, Below is a simple test class I made, you can refer to it on
the two methods:

==========================
<Serializable()> Public Class EmployeeBase
    Inherits NameObjectCollectionBase

    Private _de As New DictionaryEntry

    Private _name As String


    Public Sub New()
    End Sub

    Public Sub New(ByVal d As IDictionary, ByVal bReadOnly As [Boolean])
        Dim de As DictionaryEntry
        For Each de In d
            Me.BaseAdd(CType(de.Key, [String]), de.Value)
        Next de
        Me.IsReadOnly = bReadOnly
    End Sub 'New


    Protected Sub New(ByVal info As SerializationInfo, ByVal context As
StreamingContext)
        MyBase.New(info, context)

        Dim name As String

        name = info.GetValue("EmployeeBase.Name", GetType(String))

        _name = name
    End Sub


    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property


    Default Public ReadOnly Property Item(ByVal index As Integer) As
DictionaryEntry
        Get
            _de.Key = Me.BaseGetKey(index)
            _de.Value = Me.BaseGet(index)
            Return _de
        End Get
    End Property


    Default Public Property Item(ByVal key As [String]) As [Object]
        Get
            Return Me.BaseGet(key)
        End Get
        Set(ByVal Value As [Object])
            Me.BaseSet(key, Value)
        End Set
    End Property

    Public ReadOnly Property AllKeys() As [String]()
        Get
            Return Me.BaseGetAllKeys()
        End Get
    End Property


    Public ReadOnly Property AllValues() As Array
        Get
            Return Me.BaseGetAllValues()
        End Get
    End Property


    Public ReadOnly Property AllStringValues() As [String]()
        Get
            Return
CType(Me.BaseGetAllValues(Type.GetType("System.String")), [String]())
        End Get
    End Property


    Public ReadOnly Property HasKeys() As [Boolean]
        Get
            Return Me.BaseHasKeys()
        End Get
    End Property


    Public Sub Add(ByVal key As [String], ByVal value As [Object])
        Me.BaseAdd(key, value)
    End Sub 'Add

    Public Overloads Sub Remove(ByVal key As [String])
        Me.BaseRemove(key)
    End Sub 'Remove

    Public Overloads Sub Remove(ByVal index As Integer)
        Me.BaseRemoveAt(index)
    End Sub 'Remove


    Public Sub Clear()
        Me.BaseClear()
    End Sub 'Clear

    Public Overrides Sub GetObjectData(ByVal info As
System.Runtime.Serialization.SerializationInfo, ByVal context As
System.Runtime.Serialization.StreamingContext)

        MyBase.GetObjectData(info, context)

        info.AddValue("EmployeeBase.Name", _name, GetType(String))
    End Sub
End Class
==============================

Hope this helps.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
Author
16 Feb 2006 4:20 PM
Denny
Yes, that solution worked! Thank you for your quick response.

--
DENNY BROWNE
Show quote
"Steven Cheng[MSFT]" <stch***@online.microsoft.com> wrote in message
news:D1qS4rtMGHA.768@TK2MSFTNGXA01.phx.gbl...
> Hi Denny,
>
> Welcome to the MSDN newsgroup.
>
> From your description, I understand you have developed a custom class
> which
> derives from "NameObjectCollectionBase" class. The class also has a custom
> string property named "Name". In your .net remoting application, you use a
> server object to return an instance of this custom class to client-side.
> However, you found that the returned custom class instance always have
> empty "Name" value, correct?
>
> Based on the code snippet you provided, I've also done some tests by
> creating a simple custom class inheriting from NameObjectCollectionBase
> and
> I did encounter the problem you mentioned.  After doing some further
> research, I found that the problem is caused by the base class
> "NameObjectCollectionBase". Since "NameObjectCollectionBase" class has
> implemented the "ISerializable" interface, when the .net runtime
> serializing the custom class instance, it will call the "GetObjectData"
> method of the "NameObjectCollectionBase" class. However,
> "NameObjectCollectionBase" class's  "GetObjectData" method only save its
> own properties, so our sub class's property values are lost.  To resolve
> this problem, we need to explicitly override the
> "ISerializable.GetObjectData" method to store our own class's property(if
> you want to persist it). In addition, we also need to retrieve the data
> back from the SerializationInfo collection in the deserialization
> constructor, Below is a simple test class I made, you can refer to it on
> the two methods:
>
> ==========================
> <Serializable()> Public Class EmployeeBase
>    Inherits NameObjectCollectionBase
>
>    Private _de As New DictionaryEntry
>
>    Private _name As String
>
>
>    Public Sub New()
>    End Sub
>
>    Public Sub New(ByVal d As IDictionary, ByVal bReadOnly As [Boolean])
>        Dim de As DictionaryEntry
>        For Each de In d
>            Me.BaseAdd(CType(de.Key, [String]), de.Value)
>        Next de
>        Me.IsReadOnly = bReadOnly
>    End Sub 'New
>
>
>    Protected Sub New(ByVal info As SerializationInfo, ByVal context As
> StreamingContext)
>        MyBase.New(info, context)
>
>        Dim name As String
>
>        name = info.GetValue("EmployeeBase.Name", GetType(String))
>
>        _name = name
>    End Sub
>
>
>    Public Property Name() As String
>        Get
>            Return _name
>        End Get
>        Set(ByVal value As String)
>            _name = value
>        End Set
>    End Property
>
>
>    Default Public ReadOnly Property Item(ByVal index As Integer) As
> DictionaryEntry
>        Get
>            _de.Key = Me.BaseGetKey(index)
>            _de.Value = Me.BaseGet(index)
>            Return _de
>        End Get
>    End Property
>
>
>    Default Public Property Item(ByVal key As [String]) As [Object]
>        Get
>            Return Me.BaseGet(key)
>        End Get
>        Set(ByVal Value As [Object])
>            Me.BaseSet(key, Value)
>        End Set
>    End Property
>
>    Public ReadOnly Property AllKeys() As [String]()
>        Get
>            Return Me.BaseGetAllKeys()
>        End Get
>    End Property
>
>
>    Public ReadOnly Property AllValues() As Array
>        Get
>            Return Me.BaseGetAllValues()
>        End Get
>    End Property
>
>
>    Public ReadOnly Property AllStringValues() As [String]()
>        Get
>            Return
> CType(Me.BaseGetAllValues(Type.GetType("System.String")), [String]())
>        End Get
>    End Property
>
>
>    Public ReadOnly Property HasKeys() As [Boolean]
>        Get
>            Return Me.BaseHasKeys()
>        End Get
>    End Property
>
>
>    Public Sub Add(ByVal key As [String], ByVal value As [Object])
>        Me.BaseAdd(key, value)
>    End Sub 'Add
>
>    Public Overloads Sub Remove(ByVal key As [String])
>        Me.BaseRemove(key)
>    End Sub 'Remove
>
>    Public Overloads Sub Remove(ByVal index As Integer)
>        Me.BaseRemoveAt(index)
>    End Sub 'Remove
>
>
>    Public Sub Clear()
>        Me.BaseClear()
>    End Sub 'Clear
>
>    Public Overrides Sub GetObjectData(ByVal info As
> System.Runtime.Serialization.SerializationInfo, ByVal context As
> System.Runtime.Serialization.StreamingContext)
>
>        MyBase.GetObjectData(info, context)
>
>        info.AddValue("EmployeeBase.Name", _name, GetType(String))
>    End Sub
> End Class
> ==============================
>
> Hope this helps.
>
> Regards,
>
> Steven Cheng
> Microsoft Online Support
>
> Get Secure! www.microsoft.com/security
> (This posting is provided "AS IS", with no warranties, and confers no
> rights.)
>
>
Author
17 Feb 2006 1:14 AM
Steven Cheng[MSFT]
You're welcome Denny,

Have a good day!

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

AddThis Social Bookmark Button