Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get notification of object disposal/destruction

I need a way to track instances of various classes, without those classes having any knowledge that they are being tracked. Essentially, I have a class factory which creates instances and hands them off to another thread. Once that thread completes and unloads the instance, I need to get notified of that so I can do reference counting and exit from my class factory when all the instances are gone.

The challenge is that I can't modify any of the classes I'll bve loading, because I don't control their source code.

Tracking the instances I create is simple, I can just put them in some sort of collection as I create them. Tracking their destruction is causing me problems. If I could modify the source code, I'd add an event to each class and when I create an instance, I'd hook into the event and use that as my notification. But I can't do that.

So, the question is this: is there a sneaky way to monitor an object instance and detect when it is being destroyed?

like image 345
Tim Long Avatar asked Jul 16 '10 18:07

Tim Long


4 Answers

Since you're creating the objects, it seems like you could return a Decorator instead of the actual instance.

By using the Decorator Pattern, you could "wrap" the returned object in your own, decorated API. The decoration could provide an IDisposable implementation that provided your destruction notification.

like image 176
Reed Copsey Avatar answered Nov 19 '22 02:11

Reed Copsey


There isn't a way to get active notification, but you could keep a WeakReference to the objects and periodically check if any have died.

Edit: I like Reed's answer better than mine!

like image 35
Stephen Cleary Avatar answered Nov 19 '22 04:11

Stephen Cleary


If you hold a list of the references to the instances you create they will not get garbage collected and so will never be destroyed...

Instead you can create a repository that holds a list of Guids and create a new Guid for each instance and then add it to a list instead - something like a FactoryRepository. In this way you do not have a reference problem for garbage collection as Guids are structs rather than reference types. You could then inherit from each class to create a type that can notify on destroy. I am assuming that as you cannot alter the code of the original classes, you cannot also alter the consumers of these classes, therefore something like the decorator pattern (via an interface) is out because the types would not be compatible.

Very simplified example:

public class OriginalClassDestroyNotifier : OriginalClass
{
    private readonly Guid _instanceId;

    public OriginalClassDestroyNotifier(Guid instanceId)
    {
        _instanceId = instanceId;
    }

    ~OriginalClassDestroyNotifier()
    {
        FactoryRepository.NotifyDestroyed(_instanceId);
    }
}
like image 31
Tim Lloyd Avatar answered Nov 19 '22 02:11

Tim Lloyd


How about you control the destruction of the object:

public void Destroy(T obj)
{
    if (obj == null)
        throw new ArgumentNullException("obj");
    if (!_living.Contains(obj))
        throw new ArgumentException("Where did this obj come from?");

    using (obj as IDisposable)
    {

    }

    _living.Remove(obj); // List?
}
like image 39
ChaosPandion Avatar answered Nov 19 '22 02:11

ChaosPandion