Problem with EventSubscription/Publication

Topics: CAB & Smart Client Software Factory
Oct 6, 2005 at 3:50 AM
originally posted by: DLorenz

First, I have to mention that the project I am working on is actually in VB.NET, using the CAB .dlls in the background. I am unsure if this will cause quirky things to happen.

Anyway, right now I have an EventSubscription inside of a SmartPart that subcribes to an event in a controller from a child workitem. If I terminate the WorkItems (sending me back to the Main Menu) and come back down, the EventPublication gets an error that the target of invocation is essentially null. Isn't Terminate() supposed to remove those EventSubscriptions? Or is this something that will be fixed in the next release of CAB? Thanks.

On a side-note, another VB.NET quirky thing is that when I call WorkItem.Activate, it doesn't bring the SmartParts in that workitem to the front. I thought this worked in C#, though.
Oct 6, 2005 at 6:44 AM
originally posted by: DLorenz

After looking into this matter deeper, I've found something rather disconcerting. When the dispose method is called on the SmartPart, it will remove certain things, like data from a grid. It will also set IsDisposed to True. However, the object remains. When you make a check to see if the target is null,

private void InvokeInstance(object sender, EventArgs args)
{
object target = this.wrSubscriber.Target;
if (target == null)
{
this.topic.RemoveSubscriber(this);
return;
}
this.method.Invoke(target, new object[] { sender, args });
}

that won't actually be true. So then the event will go to an item that is actually set to be disposed. Though, I guess the easy way around this is to check to see if the object the subscriber resides in is actually disposed. I don't see an easy way for MS to fix this since object doesn't have a IsDisposed flag.
Oct 8, 2005 at 3:02 PM
originally posted by: Phyrefly

In the CompositeContainer class, the dipose method is defined as shown below:

protected override void Dispose(bool disposing)
{
if (disposing)
{
isDisposing = true;
object[] copy = new objectitems.Count;
items.Values.CopyTo(copy, 0);
foreach (object theItem in copy)
{
if (theItem is IDisposable)
{
((IDisposable)theItem).Dispose();
if (theItem is IComponent)
{
IComponent comp = (IComponent)theItem;
comp.Site = null;
}

}
}
items.Clear();
}
base.Dispose(disposing);
}

So, therefore we can see that an object's site is set to null when it's parent is disposed ;)


So, u can simply cast the object to an IComponent, and then check to see if it its site has been set to null, like this:

private void InvokeInstance(object sender, EventArgs args)
{
object target = this.wrSubscriber.Target;
bool disposed = false;
if (target is IComponent)
{
IComponent comp = (IComponent)target;
if(comp.Site == null)
disposed = true;
}
if (target == null || disposed)
{
this.topic.RemoveSubscriber(this);
return;
}
this.method.Invoke(target, new object[] { sender, args });
}

Admittedly, this will only work if all your subscribers implement IComponent :)
(which I know is true for Controllers and UserControls - "Smartparts")