(2.0) Proper way to handle child events?

(2.0) Proper way to handle child events?

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


Brian Criswell posted on Monday, June 05, 2006

Many examples have been given for CSLA 1.x showing how to have a parent object listen in on the ListChanged and IsDirtyChanged events so that the parent object knows to fire its IsDirtyChanged event.  The examples show which methods to override so that the events are hooked up properly on object create, fetch, deserialize and cancel edit. My question is which methods must be overridden in 2.0 to properly ensure the parent's event handlers are properly set up for each of these situations (and any I am missing)?

RockfordLhotka replied on Monday, June 05, 2006

The places where you need to add the handler hookup are:

  1. in an override of OnDeserialized()
  2. in your constructor(s) (assuming you create the object in the child object reference field's declaration like I do in the book
  3. any time you set the child object reference in your code (childRef = blah), which is commonly done in the DataPortal_XYZ methods

The hookups for child objects in a collection are already part of BusinessListBase and so no extra work is required there. You only need to do this extra work in a BusinessBase-derived parent object.

Make sure to properly unhook the event handler in the case of #3 as well! Failure to do that can result in dangling references and thus effectively memory leaks.

Brian Criswell replied on Tuesday, June 06, 2006

Thanks for the response, Rocky.  I had been bitten by my events stopping working after a CancelEdit() in 1.52, which I am assuming 1.53 fixes, but I wanted to make sure I was not missing anything in the move to 2.0.

RockfordLhotka replied on Tuesday, June 06, 2006

If the events do cut off in that case then it is a bug, so please let me know so I can fix it.


From: Brian Criswell [mailto:cslanet@lhotka.net]
Thanks for the response, Rocky.  I had been bitten by my events stopping working after a CancelEdit() in 1.52, which I am assuming 1.53 fixes, but I wanted to make sure I was not missing anything in the move to 2.0.

Brian Criswell replied on Tuesday, June 06, 2006

Well, here is a link to my old MSN forum post. http://groups.msn.com/cslanet/general.msnw?action=get_message&mview=0&ID_Message=25568&LastModified=4675564369390016792

Basically, I had an object that had objects all the way down to the great grandchild level.  Changing a lookup value in a great grandchild object would be caught by the child object and possibly change the value of a lookup in the child object.  If I did a CancelEdit() on the parent, disposed the form and then added it back to a new instance of the form, changing the lookup in a great grandchild would have no effect on the corresponding child.  Unfortunately, I have not had an opportunity to test this under 1.53.

tetranz replied on Monday, July 24, 2006

Resurecting other old post topic. Sorry if I'm a bit behind. Smile [:)]

I nearly always do (3) below to hook ListChanged events in my parent to fire IsDirtyChanged.

Where is the correct place to unhook the events? Should I override Clone() and unhook before base.Clone()?

A little off topic but referring to (2) below. I tend to not create a new collection in the reference field (I leave it null)  but create it in DataPortal_Create. I also hook the events there. I just seems more consistent with DataPortal_Fetch. Am I missing a reason to do it differently?

Thanks
Ross

RockfordLhotka:

The places where you need to add the handler hookup are:

  1. in an override of OnDeserialized()
  2. in your constructor(s) (assuming you create the object in the child object reference field's declaration like I do in the book
  3. any time you set the child object reference in your code (childRef = blah), which is commonly done in the DataPortal_XYZ methods

The hookups for child objects in a collection are already part of BusinessListBase and so no extra work is required there. You only need to do this extra work in a BusinessBase-derived parent object.

Make sure to properly unhook the event handler in the case of #3 as well! Failure to do that can result in dangling references and thus effectively memory leaks.

RockfordLhotka replied on Monday, July 24, 2006

Regarding #2, creating the collection in DataPortal_Create() should be totally acceptible.
 
Regarding #3, this is one case where the unhooking is (probably) least important. The reason being that an event is really a reference from the source (child) to the subscriber (parent). If you are in the process of dropping your reference to the child, then the GC will get it - ASSUMING NOTHING ELSE REFERENCES THAT CHILD.
 
It is that last bit where you need to be careful. If you have a straightforward app, where the only thing referencing your objects is data binding, then it is most likely the case that nothing else would be referencing the child, and you have no problem.
 
But if you have a more complex app, with objects referencing other objects, or multiple forms referencing the same objects or whatever - then you could end up with something still referencing that old child, and it still referencing the parent and you could have some unintended consequences (memory leaks, errant events, etc.)
 
What I was specifically referring to in #3 is the common case where you are in DataPortal_XYZ, and you create a new instance of your child.
 
In DataPortal_Fetch the reference was probably null to start, so there's no unhook issue, but you should do a hook.
 
In DataPortal_Insert/Update the reference was probably to an object, so doing an unhook is wise.
 
Then you need to handle the deserialization case - where the objects come back from the app server. This is best done by overriding OnDeserialized() - a method I put into the framework to support this exactly scenario. That should cover both data portal and Clone() cases automatically.
 
Rocky


From: tetranz [mailto:cslanet@lhotka.net]
Sent: Monday, July 24, 2006 9:43 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] (2.0) Proper way to handle child events?

Resurecting other old post topic. Sorry if I'm a bit behind. Smile <img src=" src="/emoticons/emotion-1.gif">

I nearly always do (3) below to hook ListChanged events in my parent to fire IsDirtyChanged.

Where is the correct place to unhook the events? Should I override Clone() and unhook before base.Clone()?

A little off topic but referring to (2) below. I tend to not create a new collection in the reference field (I leave it null)  but create it in DataPortal_Create. I also hook the events there. I just seems more consistent with DataPortal_Fetch. Am I missing a reason to do it differently?

Thanks
Ross

RockfordLhotka:

The places where you need to add the handler hookup are:

  1. in an override of OnDeserialized()
  2. in your constructor(s) (assuming you create the object in the child object reference field's declaration like I do in the book
  3. any time you set the child object reference in your code (childRef = blah), which is commonly done in the DataPortal_XYZ methods

The hookups for child objects in a collection are already part of BusinessListBase and so no extra work is required there. You only need to do this extra work in a BusinessBase-derived parent object.

Make sure to properly unhook the event handler in the case of #3 as well! Failure to do that can result in dangling references and thus effectively memory leaks.




Copyright (c) Marimer LLC