Problem with BusinessBase.Parent after serialization!

Problem with BusinessBase.Parent after serialization!

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


geordiepaul posted on Tuesday, May 15, 2007

We have a slight problem when binding a BusinessListBase to a 3rd part grid component. Under the hood ths grid component must do some serialization of the object during databinding and as a result the state of the BusinessBase.Parent property is returning null. Our object requires this to work.

I have noticed in BusinessBase that _parent is marked as [NonSerialized()] but there is a handler for deserialization on BusinessListBase that resets the parent when deserialization occurs!

Am I missing something that we're required to do in order for BusinessBase.Parent to maintain it's state during deserialization? As a quick test I removed the [NonSerialized()] from _parent on BusinessBase and everything worked but obviously this is not a real solution.

Thanks

RockfordLhotka replied on Tuesday, May 15, 2007

It sounds like the grid is serializing the child object outside the context of the list, rather than serializing the list itself.

What grid is this? That's not a particularly safe/good/supported thing to do!

I don't know how you can address this. If you can determine when this deserialization has happened (like in the UI or something?) perhaps you can call a method (of your creation) on the list object to tell it to reset the parent reference.

Or perhaps you can add an event to your child object so it can raise that event to tell the list that it has been deserialized? That could be very tricky to get right, but could maybe work. It might not though - because this grid control almost certainly deserializes the child first and then re-adds it to the list.

Ahh, maybe that is the answer. In your list class you could override the method from BindingList<T> that is called when an item is replaced in the list and call SetParent() on the child from within that method. I bet that work work.

geordiepaul replied on Wednesday, May 16, 2007

Hi

Thanks for the reply.

It turns out that the grid is actually cloning the object which in turn serializes the object and causes the problem. The grid in question is Teleriks (www.telerik.com)

There suggested fix was the override the GetClone method and reset the parent object like so...

protected override object GetClone() 
   Item clone = (Item) base.GetClone(); 
    (clone as Csla.Core.IEditableBusinessObject).SetParent(this.Parent); 
    return clone; 
} 

Not sure if this is a valid fix as yet as we have encountered a problem with the SetItem method on BusinessListBase in that it does not set the Parent property like InsertItem does.

RockfordLhotka replied on Thursday, May 17, 2007

Interesting – yes I see where the SetItem method should call SetParent(). Worse, it also needs to ensure that the “new object’s” edit level is correct by decreasing or increasing it to match the list.

 

I’ve make these changes in a way that I think is correct – here’s the new method. Can you test it to see if it resolves your issue?

 

Thanks, Rocky

 

    protected override void SetItem(int index, C item)

    {

      C child = default(C);

      if (!(ReferenceEquals((C)(this[index]), item)))

        child = this[index];

      // replace the original object with this new

      // object

      bool oldRaiseListChangedEvents = this.RaiseListChangedEvents;

      try

      {

        this.RaiseListChangedEvents = false;

        // set parent reference

        item.SetParent(this);

        // if item's edit level is too high,

        // reduce it to match list

        while (item.EditLevel > this.EditLevel)

          item.AcceptChanges();

        // reset EditLevelAdded if necessary

        if (child.EditLevelAdded > this.EditLevel)

          child.EditLevelAdded = this.EditLevel;

        // if item's edit level is too low,

        // increase it to match list

        while (item.EditLevel < this.EditLevel)

          item.CopyState();

        base.SetItem(index, item);

      }

      finally

      {

        this.RaiseListChangedEvents = oldRaiseListChangedEvents;

      }

      if (child != null)

        CopyToDeletedList(child);

      OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));

    }

 

 

From: geordiepaul [mailto:cslanet@lhotka.net]
Sent: Wednesday, May 16, 2007 7:24 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Problem with BusinessBase.Parent after serialization!

 

Hi

Thanks for the reply.

It turns out that the grid is actually cloning the object which in turn serializes the object and causes the problem. The grid in question is Teleriks (www.telerik.com)

There suggested fix was the override the GetClone method and reset the parent object like so...

protected override object GetClone() 

   Item clone = (Item) base.GetClone(); 

    (clone as Csla.Core.IEditableBusinessObject).SetParent(this.Parent); 

    return clone; 

} 

Not sure if this is a valid fix as yet as we have encountered a problem with the SetItem method on BusinessListBase in that it does not set the Parent property like InsertItem does.



No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.467 / Virus Database: 269.7.1/805 - Release Date: 5/15/2007 10:47 AM


No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.467 / Virus Database: 269.7.1/807 - Release Date: 5/16/2007 6:05 PM

geordiepaul replied on Friday, May 18, 2007

Hi,

Thanks for looking at that issue!! :-)

Yes that appears to have resolved our issue. (We had just called set parent in our custom base object as a quick fix for us) . We don't use any of the n-level undo in our application so I can't confirm whether there are any issue on that front.

Will you be adding this change to an official release? (pre v3.0)

Once again thanks!!!

Paul

RockfordLhotka replied on Friday, May 18, 2007

I will not be creating a 2.1.5, no. This change will be in 3.0.

 

The reason I’m doing that, is because 3.0 doesn’t have any (major) breaking changes from 2.1.4 – it merely adds optional support for .NET 3.0. It really is much like a 2.1.5, but with additional goodies for those that need them.

 

Rocky

 


No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.467 / Virus Database: 269.7.3/809 - Release Date: 5/17/2007 5:18 PM

geordiepaul replied on Friday, May 18, 2007

Ok that makes sense.

We'll have to wait for the final release of 3.0 before taking advantage of this change as I tend not to like ad-hoc addition by anyone other than yourself i.e. a proper release! :-)

Many thanks

Paul

RockfordLhotka replied on Friday, May 18, 2007

No problem. This has been quite useful actually, because (combined with this other thread) it has forced me to walk through the SetItem and some other n-level undo behaviors in exquisite detail and I've been able to resolve some issues that have been hanging around for a while.

The comprehensive fix extends (unfortunately) beyond just SetItem() and into some other code, and the results are quite positive! Cool [H]

Copyright (c) Marimer LLC