2010-07-16 14 views
7

J'ai besoin d'un moyen de suivre les instances de diverses classes, sans que ces classes aient connaissance du suivi de ces dernières. Essentiellement, j'ai une usine de classe qui crée des instances et les remet à un autre thread. Une fois ce thread terminé et déchargé l'instance, j'ai besoin d'être averti de cela afin que je puisse faire le comptage des références et quitter la fabrique de ma classe lorsque toutes les instances ont disparu. Le problème est que je ne peux pas modifier les classes que je vais charger, parce que je ne contrôle pas leur code source.Recevoir une notification d'élimination/destruction d'objets

Suivre les instances que je crée est simple, je peux simplement les mettre dans une sorte de collection que je les crée. Suivre leur destruction me cause des problèmes. Si je pouvais modifier le code source, j'ajouterais un événement à chaque classe et quand je créerais une instance, j'accèderais à l'événement et l'utiliserais comme notification. Mais je ne peux pas faire ça. Donc, la question est la suivante: y a-t-il une façon sournoise de surveiller une instance d'objet et de détecter quand elle est détruite?

Répondre

3

Il n'existe pas de moyen d'obtenir une notification active, mais vous pouvez conserver un WeakReference aux objets et vérifier périodiquement s'il y a eu un décès.

Editer: J'aime la réponse de Reed mieux que la mienne!

+0

+1 C'est drôle - je pensais exactement la même chose, jusqu'à ce que je lise la partie où il disait qu'il contrôlait la construction des objets;) –

+0

Cela ressemble effectivement à ce qui pourrait être la solution la plus réalisable dans ma situation. Je vais essayer. –

+0

Je préfère le vôtre à celui de Reed car cela signifie que les clients de ce type n'ont pas besoin de connaître un type de décorateur spécial –

0

Que diriez-vous que vous contrôlez la destruction de l'objet:

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? 
} 
+0

Alors, que les appels Destroy()? Rappelez-vous que je ne peux pas contrôler les types que je charge (en fait, ils sont chargés dynamiquement à partir d'un dossier et je ne sais pas à l'avance ce que je vais y trouver). –

10

Puisque vous créez les objets, il semble que vous pourriez revenir un Decorator au lieu de l'instance réelle. En utilisant le Decorator Pattern, vous pouvez "envelopper" l'objet retourné dans votre propre API décorée. La décoration peut fournir une implémentation IDisposable qui fournit votre notification de destruction.

+0

C'est bien. Vous pouvez utiliser la refection pour générer le décorateur. Ce serait important si la classe est massive. – ChaosPandion

+0

C'est très intéressant, je vais suivre ça. Merci. –

2

Si vous tenez une liste des références aux instances que vous créez ils ne seront pas les déchets ramassés et ainsi ne sera jamais détruit ...

vous pouvez plutôt créer un référentiel qui contient une liste de Guids et créer un nouveau Guid pour chaque instance, puis l'ajouter à une liste - quelque chose comme un FactoryRepository. De cette façon, vous n'avez pas de problème de référence pour la récupération de place car les guids sont des structures plutôt que des types de référence. Vous pourriez ensuite hériter de chaque classe pour créer un type qui peut notifier sur détruire. Je suppose que comme vous ne pouvez pas modifier le code des classes d'origine, vous ne pouvez pas modifier les consommateurs de ces classes, donc quelque chose comme le modèle de décorateur (via une interface) est sorti parce que les types ne seraient pas compatibles.

exemple très simplifié:

public class OriginalClassDestroyNotifier : OriginalClass 
{ 
    private readonly Guid _instanceId; 

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

    ~OriginalClassDestroyNotifier() 
    { 
     FactoryRepository.NotifyDestroyed(_instanceId); 
    } 
}