Serializable Object Becomes Non-Serializable when databound

C

Codemonkey

Hi,

I'm developing a distributed App using .net remoting and have been having a
problem when trying to pass a Serializable MBV object after it has been
bound to controls on a windows form.

Example:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<Serializable> Public Class Item

'*************************************************
' Name: Name of the item
'*************************************************
Private mName As String = ""
Public Event NameChanged As EventHandler
Public Property Name() As String
Get
Return mName
End Get
Set(ByVal Value As String)
mName = Value
RaiseEvent NameChanged(Me, New EventArgs())
End Set
End Property

End Class

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The above code snippet defines a simple MarshalByValue class that has a
"Name" Property. The property has all the extra stuff needed for databinding
(Event etc. - Please let me know if this is wrong)

If I create an instance of this class and pass it across to a remoting
function call, everything works fine... the object reaches the other side
without a problem.

However, If I bind the "Name" property to a textbox on a windows form with
the following code:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
txtName.DataBindings.Add("Text", mItem, "Name")
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The databinding works, but when I call the remoting function call as before,
the following exception is raised:

"The type System.Windows.Forms.BindToObject in Assembly
System.Windows.Forms, Version=1.0.3300.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089 is not marked as serializable."

I could understand if "BindToObject" was a member of my "Item" class, but it
isn't, so why is the Remoting Framework attempting to serialize it?

Please help me with this. If you have the time, feel free to send me in the
right direction as far as databinding goes (I'm only going of an example I
found somewhere before).

Thanks in advance of any help,

Trev.
 
J

Jay B. Harlow [MVP - Outlook]

Codemonkey,
I believe the framework is trying to serialize the event handlers attached
to NameChanged. One of the handlers its attached to a class that is not
serializable. At least that is what was handing in one of my projects.

I'm not sure how to avoid excluding the event from serialization other than
implementing the ISerializable interface.

The following articles provide a wealth of information on serialization:

http://msdn.microsoft.com/msdnmag/issues/02/04/net/
http://msdn.microsoft.com/msdnmag/issues/02/07/net/
http://msdn.microsoft.com/msdnmag/issues/02/09/net/

Hope this helps
Jay
 
J

Joe White

I'm not sure how to avoid excluding the event from serialization other
than
implementing the ISerializable interface.

Does it work to tag the event with a [NonSerialized] attribute?
 
J

Jay B. Harlow [MVP - Outlook]

Joe,
Unfortunately you cannot put the NonSerialized attribute on an Event within
VB.NET, as an Event is not a Field. (it has an hidden underlying field).
NonSerialized can only be applied to Fields.

I have not played with C# enough in the Event area to know if its any better
there. I know you can have an 'event procedures' similar to property
procedures, however I have not used them enough to know any specifics. Also
the OP was talking VB.NET, so I did not feel its appropriate to tell him
what MAY be possible in C# (especially when I don't know for certain).

Hope this helps
Jay

Joe White said:
I'm not sure how to avoid excluding the event from serialization other than
implementing the ISerializable interface.

Does it work to tag the event with a [NonSerialized] attribute?
 
K

Karen Martinez

You can mark an event as not serialized in C#. Since you're using VB.NET,
you could have one class in another project (a C# class library) that
contains your events, and then inherit your business class from it.

[Serializable()]
public abstract class MyBaseClass
{
[field: NonSerialized]
public event EventHandler NameChanged;

protected virtual void OnNameChanged() {
if (NameChanged != null) {
NameChanged(this, EventArgs.Empty);
}
}
}
 
J

Jay B. Harlow [MVP - Outlook]

Karen,
[field: NonSerialized]
public event EventHandler NameChanged;
Drats! :) VB.NET only supports Assembly & Module modifiers on attributes

<Assembly: NonSerialized>
or
<Module: NonSerialized>

The Field modifier is not supported.

Of course NonSerialized in not appropriate for either. I believe the Module
attribute modifier is for .NET IL Modules, not VB.NET Module types.
You can mark an event as not serialized in C#. Since you're using VB.NET,
you could have one class in another project (a C# class library) that
contains your events, and then inherit your business class from it.
Its about as easy to implement ISerializable and serialize each field
individually. I'm not sure how the OP feels about either solution.

Thanks for the tip on the 'field' modifier for the attributes in C#. Safely
stored that nugget of knowledge for later.

Jay

Karen Martinez said:
You can mark an event as not serialized in C#. Since you're using VB.NET,
you could have one class in another project (a C# class library) that
contains your events, and then inherit your business class from it.

[Serializable()]
public abstract class MyBaseClass
{
[field: NonSerialized]
public event EventHandler NameChanged;

protected virtual void OnNameChanged() {
if (NameChanged != null) {
NameChanged(this, EventArgs.Empty);
}
}
}
 
C

Codemonkey

Jay,

Cheers for the help.

Is the short term for testing, I've discovered that if I remove that
databindings from the object before serializing it, it works fine.

I'll probably go down the root of implementing ISerializable in the near
future. Seems like the only "clean" way to do it from VB.net.

Has anybody noticed this problem with VS 2003 and .net 1.1? I'm using VS
2002 and .net 1.0. Hopefully I should be upgrading in the next few weeks.

Cheers again

Trev.
 
C

Codemonkey

Nope, Tried that. The <NonSerialized> attribute can't be applied to events
in VB :-(


Joe White said:
I'm not sure how to avoid excluding the event from serialization other than
implementing the ISerializable interface.

Does it work to tag the event with a [NonSerialized] attribute?
 
C

Codemonkey

Karen,

Cheers for the tip, but I don't fancy the idea of my business logic being
spread between 2 classes in two separate projects for the sake of a few
events.

Databinding isn't that important to me ;-) (Although I haven't tried it when
a standard event handler (non databinding) is attached to the event).

Cheers,

Trev.
 
K

Karen Martinez

The same problem exists in the 2003 version, unfortunately. It seems a
shame to write a bunch more code to work around this issue. Common Refrain:
Hopefully Microsoft will get around to doing something about it in the next
version of VS.NET.

Karen
 
C

Codemonkey

Thanks for the tip about VS 2003.
It seems a shame to write a bunch more code to work around this issue.

Yeah - I'm sure it isn't the only thing that I've had to code around. ;-)

I'll eventually go down the ISerialize way of doing things as I've
discovered that it happens with all event handlers, not just the databinding
variety. Basically if objectA attaches a handler to objectB's event, then
when objectB is serialized, objectA is serialized along with it. Guess this
must be by design :-S

Pity about the difference between the VB <NonSerialized> attribute and the
C# one.

Cheers again,

Trev.
 
J

Jay B. Harlow [MVP - Outlook]

Trev,
Pity about the difference between the VB <NonSerialized> attribute and the
C# one.
I submitted something to Microsoft about this, we can hope that Whidbey
(VS.NET 2004) offers a change in this area.

Jay
 
J

Joe Fallon

This exact problem is outlined by Rocky Lhotka in his CSLA Business Objects
Framework.
He solves it the same way too!
Uses a C# base class to prevent serializing the event handler.
--
Joe Fallon




Jay B. Harlow said:
Karen,
[field: NonSerialized]
public event EventHandler NameChanged;
Drats! :) VB.NET only supports Assembly & Module modifiers on attributes

<Assembly: NonSerialized>
or
<Module: NonSerialized>

The Field modifier is not supported.

Of course NonSerialized in not appropriate for either. I believe the Module
attribute modifier is for .NET IL Modules, not VB.NET Module types.
You can mark an event as not serialized in C#. Since you're using VB.NET,
you could have one class in another project (a C# class library) that
contains your events, and then inherit your business class from it.
Its about as easy to implement ISerializable and serialize each field
individually. I'm not sure how the OP feels about either solution.

Thanks for the tip on the 'field' modifier for the attributes in C#. Safely
stored that nugget of knowledge for later.

Jay

Karen Martinez said:
You can mark an event as not serialized in C#. Since you're using VB.NET,
you could have one class in another project (a C# class library) that
contains your events, and then inherit your business class from it.

[Serializable()]
public abstract class MyBaseClass
{
[field: NonSerialized]
public event EventHandler NameChanged;

protected virtual void OnNameChanged() {
if (NameChanged != null) {
NameChanged(this, EventArgs.Empty);
}
}
}
 
J

Jay B. Harlow [MVP - Outlook]

Joe,
It never hurts for multiple people to inform MS of it.

If enough people show that its a problem I suspect MS will be more inclined
on fixing it.

Thanks for the confirmation.

Jay
 
G

Gery D. Dorazio

Hi folks,

This problem looks very much like a related situation in what appears to be
a loss of state in the server object with many of the remoting
samples...ones that instantiate a Singleton object forever on the server and
then have multiple clients access it... In this problem, losing the
reference to the event handler appears to be the same thing. I have also
lost the same type of reference to event handlers.

In a generalized case, if you start a server and leave it running and then
start a client, let it do its thing and then start another client, it
appears to have reinitialized the server instances objects - except the
serializable ones like strings. (If anyone is interested I have a project I
can email to you to demonstrate.)

However, I am beginning to think that this situation is by design and that
there really isn't a problem here. In the MS documentation it states that
when designing remotable classes the designer must insure that the class
properly handles security since remotable objects cross process boundries
and/or app domains. Although the framework handles security for local apps,
it doesn't automatically extend to remotable types because the security
context can be outside the local machines control. It wouldn't necessarily
throw a security exception because the framework doesn't know your
intentions about the use of the fields or references in your class. This
idea is hinted at because between framework 1.0 and 1.1 the security
restrictions were tightened and now you have to add the
typeFilterLevel="Full" attribute to the formatter. Otherwise, some apps
developed in 1.0 will give a security exception in 1.1.

I do not know if this is the problem here and this may be an incorrect
rabbit trail. But the thought here is that when a second instance of a
client is instantiated, a second singleton object is also instantiated
because the first instance is/was used for the first client and the
boundries are different. I am currently trying to figure out how to test
this theory by using the ObjRef object returned by the
RemotingServices.Marshall() call that I use on the server after creating the
first instance of the singleton object. But I am not there yet...

Any comments good or bad are very welcome.

Thanks,
Gery


--
Gery D. Dorazio
Development Engineer

EnQue Corporation
1334 Queens Road
Charlotte, NC 28207
(704) 377-3327
www.enque.net
 
C

Codemonkey

Gery,

The root of the problem that I was having was that any objects attached to
an event on an object being serialized would be serialized too. (If a
handles b's event, when b is serialized, a is serialized along with it). The
error was being caused by some non-serializable object in the databinding
hierarchy attaching itself to my event. A nice solution would be to mark the
event as NonSerialized, but this can't be done in VB as explained in
previous posts.

I don't think the problem you've mentioned is too closely related to what
I'm experiencing. I hope you find an explanation or solution.

Best Regards,

Trev.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top