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?
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.
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!
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);
}
}
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?
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With