OnDeserializedHandler

OnDeserializedHandler

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


ajj3085 posted on Friday, April 13, 2007

Hi,

I'm overriding OnDeserialized in my BLB class, to handle resetting some references after deserialization.

The problem I'm running into is that OnDeserializedHandler calls OnDeserialized BEFORE it has set the parent objects for all children in the collection.  Because of this, I can't get my OnDeserialized to do what it needs to, as my handler needs the parent already in place.

Has anyone else encountered this, and is so, how have you handled it?  Is there a reason OnDeserialized is called first?  If so, could an OnDeserializedComplete hook be added in as well?

Thanks
Andy

ajj3085 replied on Friday, April 13, 2007

I made the change to Csla that will call OnDeserialized after the Parent properties are reset, and this solves my problem.

So Rocky, in the spirit of not breaking backward compatability, could we get an OnDeserializedComplete that fires after the items in the collection have their parents set?

I'd do this in my own BLB subclass, but I'm not sure which method would get called if both classes in the inheritance chain have an OnDeserialized attribute applied, or if both get called, but I don't know the order.

Andy

xal replied on Friday, April 13, 2007

How about handling stuff from the parent? You could have an OnDeserializedComplete method in your child and the parent could call that when it's fully deserialized...


Andrés

ajj3085 replied on Friday, April 13, 2007

Well, I do handle it in the parent.  The problem is its parent has not yet been set, and it needs to give that information to the children.

The ultimate parent could handle it, but then it needs to know more about its children; some get the ultimate parent, some do not..  its a bit confusing I know, but the requirements in this area are pretty heavy.

ajj3085 replied on Thursday, May 10, 2007

Just wanted to bump this up; is there any reason that Parent shouldn't be set before the OnDeserialized method is called in BusinessListBase.

This is the code I changed:
    [OnDeserialized()]
    private void OnDeserializedHandler(StreamingContext context)
    {
      OnDeserialized(context);
      foreach (Core.IEditableBusinessObject child in this)
      {
        child.SetParent(this);
        INotifyPropertyChanged c = child as INotifyPropertyChanged;
        if (c != null)
          c.PropertyChanged += new PropertyChangedEventHandler(Child_PropertyChanged);
      }
      foreach (Core.IEditableBusinessObject child in DeletedList)
        child.SetParent(this);
    }

to

    [OnDeserialized()]
    private void OnDeserializedHandler(StreamingContext context)
    {
      foreach (Core.IEditableBusinessObject child in this)
      {
        child.SetParent(this);
        INotifyPropertyChanged c = child as INotifyPropertyChanged;
        if (c != null)
          c.PropertyChanged += new PropertyChangedEventHandler(Child_PropertyChanged);
      }
      foreach (Core.IEditableBusinessObject child in DeletedList)
        child.SetParent(this);

      // Now sets up relationships before deserializing
      OnDeserialized(context);
    }

Anything wrong with this?  Could this change be added to the framework?

Robert replied on Friday, October 03, 2008

I see this post is old, but I ran into something simular today. Is there any good reason for not having the call last? It feels like when an object is deserialized, it should be ready to use. No? Yes?

Robert

ajj3085 replied on Friday, October 03, 2008

I'm not sure.. but I'm glad you posted this, since I had forgotten I made this change.  Of course, deserialization has changed quite a bit in 3.6.. I'll need to test my code to see if it all still works.

It looks like it does, because I don't' have tests failing... but I'll need to do more testing.

sergeyb replied on Friday, October 03, 2008

I am pretty sure this has been addressed in 3.6.  Could you give it a try and see?

 

Sergey Barskiy

Principal Consultant

office: 678.405.0687 | mobile: 404.388.1899

Magenic ®

Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: ajj3085 [mailto:cslanet@lhotka.net]
Sent: Friday, October 03, 2008 2:41 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] OnDeserializedHandler

 

I'm not sure.. but I'm glad you posted this, since I had forgotten I made this change.  Of course, deserialization has changed quite a bit in 3.6.. I'll need to test my code to see if it all still works.

It looks like it does, because I don't' have tests failing... but I'll need to do more testing.


Robert replied on Saturday, October 04, 2008

It looks like it's the same, at least in BusinessBase.

[OnDeserialized()]
private void OnDeserializedHandler(StreamingContext context)
{
   OnDeserialized(context);
   OnDeserializedInternal();
}

It may be a reson for this, but if so, it would be nice to have it explained.

Robert

sergeyb replied on Saturday, October 04, 2008

I wonder if you could just override OnDeserializedInternal and call base.OnDeserializedInternal, then do your work?

 

Sergey Barskiy

Principal Consultant

office: 678.405.0687 | mobile: 404.388.1899

Magenic ®

Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: Robert [mailto:cslanet@lhotka.net]
Sent: Saturday, October 04, 2008 5:33 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: OnDeserializedHandler

 

It looks like it's the same, at least in BusinessBase.

[OnDeserialized()]
private void OnDeserializedHandler(StreamingContext context)
{
   OnDeserialized(context);
   OnDeserializedInternal();
}

It may be a reson for this, but if so, it would be nice to have it explained.

Robert



Robert replied on Sunday, October 05, 2008

Yes, off course! "Internal" seemed so private, he he. Didn't notice it. Thanks...

Robert

PC Tech replied on Monday, October 06, 2008

It looks like overriding OnDeserializedInternal() is a good work around if you're using 3.6 but this is still a problem for us in 3.5. After studying what Rocky does in his code for BusinessBase I came up with the following solution for 3.5 (and maybe earlier?):

[System.Runtime.Serialization.OnDeserialized()]

private void OnDeserializedHandler(System.Runtime.Serialization.StreamingContext context)

{

   //this code executes after BusinessBase's OnDeserializedHandler

}

This code can go in your Business object and apparently does get called after it's counterpart in BusinessBase. We haven't had a chance to fully test the reliability of this approach but so far it does seem that methods marked with the OnDeserialized attribute in base classes get called by the serialization engine before methods in derived classes marked with the attribute. We use the above method in our business objects to reattach delegates to ListChanged events for child lists. The ListChanged event does not survive serialization and needs to be reattached after any Fetch, Create, Save, Clone, and Undo operation. If we try to override the OnDeserialized() method we encouter a similar problem to the one mentioned in one of the first posts in that the FieldManager is not initialized until after OnDeserialized() is called. The child lists we need access are managed fields.

Copyright (c) Marimer LLC