Serialization exception on a UI form?

Serialization exception on a UI form?

Old forum URL: forums.lhotka.net/forums/t/6388.aspx


triplea posted on Tuesday, February 10, 2009

Using CSLA 3.0.3 and WinForms. I have a master-detail form with a grid displaying invoice lines. Clicking on a line displays the detailed information. So my BO tree looks like this:

Invoice (EditableRoot)
   InvoiceLines (EditableChildList)
      AbstractInvoiceLine (EditableChild)
         ConcreteInvoiceLine1 (EditableChild)
         ConcreteInvoiceLine2 (EditableChild)
         (more concrete types)...

The setup worked fine until I introduced 2 public events in one of my concrete invoice line objects. My form subscribes to these 2 events when one such concrete InvoiceLine is added to its collection.

The problem that is now occuring is that if on my form I select this line on the grid, a SerializationException is thrown, which is complaining that my form is not marked as serializable. This strikes me as odd because the exception appears to be thrown in BusinessListBase.OnListChanged yet the culprit appears to be my form which is in a completly seperate assembly not referenced in my Library project...

I must have violated some rule here but it completly confuses me at the moment. Any ideas what might be causing this?

richardb replied on Tuesday, February 10, 2009

Can you mark the events as NonSerializable? 

If my memory serves me .Net tries to serialize the whole graphs and that includes things subscribed to the objects events and this is what you are seeing - it's trying to serialise the form.

triplea replied on Tuesday, February 10, 2009

Thanks for the suggestion but unfortunately the debugger says no:

Error 2 Attribute 'NonSerialized' is not valid on this declaration type. It is only valid on 'field' declarations

Your explanation seems valid yet I am completly at loss as to how specify this...

ajj3085 replied on Tuesday, February 10, 2009

Try using [field: NonSerialized] on the event variable.

triplea replied on Tuesday, February 10, 2009

Thanks that did the trick! Does this mean that all events a BO is exposing that the UI might subscribe to should be marked as NonSerialized? I am pretty sure I have done this in the past without any issues but then again I might be wrong...

ajj3085 replied on Tuesday, February 10, 2009

Either that or you can check out what Rocky does, which is to keep a seperate list of SerializableEventHandlers and NonSerializedEventHandlers.  Of course the non-serialized ones will be lost if the object is sent over the data portal and back (or serialized by any other means), and you'll need to remember to re-hook those events.

RockfordLhotka replied on Tuesday, February 10, 2009

triplea:
Thanks that did the trick! Does this mean that all events a BO is exposing that the UI might subscribe to should be marked as NonSerialized? I am pretty sure I have done this in the past without any issues but then again I might be wrong...

Yes!!

I discuss this in the book when I show the code for the PropertyChanged event in BindableBase.

The [field: NonSerialized] approach is a hack that they put into C# 1.x, but what you should really do (imo) is use the custom event declaration syntax, because that's much more explicit and doesn't rely on compiler magic.

triplea replied on Tuesday, February 10, 2009

OK its back to the book then :-)

tetranz replied on Tuesday, February 10, 2009

The form is referenced by your library through the delegate that the form supplies when subscribing to the event. When you serialize something, it tries to also serialize everything it references.

I think you need to do your event the way Rocky does the PropertyChanged event in Csla.Core.BindableBase. It unfortunately makes events between BOs and forms a lot more complicated.

I'm not sure why you're getting the problem when you select something. I had the problem when saving. My simple solution for that was to unhook the event at the start of my form's save code and rehook again after the unbind, save, rebind. That let me use normal events.

The other way that might work is simply to "borrow" the PropertyChanged event and use that. To notify your form of something, call OnPropertyChanged. Create a meaningless property if you're not really informing the form of a property change (although what else is there?). Hook that event in your form. You still need to unhook and rehook after a save or maybe to use the ListChanged event on the bindingSource which should always work if you're doing the unbind, save, rebind stuff correctly.

In general it's best to channel all BO to UI communications through the normal databinding system.

Ross

triplea replied on Tuesday, February 10, 2009

I had the hook/unhook mechanism in place but because of the nature of the problem (i.e. occur on datagridview selection change) there was no need to unhook so I was a bit stuck...

For now I will stick to the [field: NonSerialized()] solution unless it causes any issues since it appears to be the cleanest way.

Thanks!

Copyright (c) Marimer LLC