Appel de base.Dispose() automatiquement à partir de classes dérivées

Edition - Nouveau Question

Ok permet de reformuler la question de manière plus générale.

L'aide de la réflexion, est-il possible d'appeler de manière dynamique lors de l'exécution d'une méthode de classe de base que vous pouvez être prépondérantes. Vous ne pouvez pas utiliser la "base" mot-clé au moment de la compilation, car vous ne pouvez pas être sûr qu'il existe. Au moment de l'exécution, je veux la liste de mes ancêtres méthodes et d'appeler l'ancêtre des méthodes.

J'ai essayé d'utiliser GetMethods() et que telle, mais tout ce qu'ils sont de retour "pointeurs" pour la plupart des dérivés de la mise en œuvre de la méthode. Pas une mise en œuvre sur une base de classe.

Fond

Nous sommes en train de développer un système en C# 3.0 avec un relativement importante de la hiérarchie de classe. Certaines de ces classes, n'importe où dans la hiérarchie, ont des ressources qui doivent être
éliminés, ceux de mettre en œuvre la IDisposable interface.

Le Problème

Maintenant, pour faciliter la maintenance et refactoring du code, je voudrais trouver un moyen, pour les classes de mise en œuvre de IDisposable,
pour "automatiquement" appel de base.Dispose(bDisposing) si tout ancêtres met également en œuvre IDisposable. De cette façon, si un peu de classe à un niveau supérieur dans la hiérarchie commence à mettre en œuvre
ou s'arrête la mise en œuvre de IDisposable qui seront pris en charge automatiquement.

La question est de deux plis.

  • Tout d'abord, trouver si tout ancêtres implémente IDisposable.
  • Deuxième, appel de base.Dispose(bDisposing) sous certaines conditions.

La première partie, la recherche sur les ancêtres de mise en œuvre de IDisposable, j'ai été en mesure de traiter avec.

La deuxième partie est difficile. Malgré tous mes
efforts, je n'ai pas été en mesure d'appeler la base.Dispose(bDisposing) à partir d'une classe dérivée. Toutes mes tentatives ont échoué. Ils causée
des erreurs de compilation ou de l'appelé la mauvaise méthode dispose (), qui est la plus dérivée, donc en boucle pour toujours.

Le principal problème est que vous ne peut pas se réfèrent en fait à la base.Dispose() directement dans votre code si il n'y a pas une telle chose comme un
ancêtre de la mettre en œuvre (être rappelé qu'il n'ont pas d'ancêtres encore la mise en œuvre de IDisposable, mais je veux que le dérivé de code pour être prêt quand et si ces
une chose qui se passe dans le futur
). Qui nous laissent avec le Réflexion mécanismes, mais je n'ai pas trouvé une bonne façon de le faire. Notre code est assez rempli avec
avancée des techniques de réflexion et je pense que je n'ai pas manqué de rien d'évident là.

Ma Solution

De mon mieux était encore d'avoir quelques conditionnel du code à l'aide de code commenté. La modification de la IDisposable hiérarchie soit de briser la construction
(si pas de IDisposable ancêtre existe) ou lève une exception (si il y a IDisposable ancêtres, mais de la base.Jeter n'est pas appelé).

Voici un code que j'ai écris pour vous montrer ce que mon Aliéner(bDisposing) méthode ressemble. Je suis en train de mettre ce code à la fin de tous les Dispose()
méthodes tout au long de la hiérarchie. Toutes les nouvelles classes sont créées à partir de modèles, qui comprend également présent code.

public class MyOtherClassBase
{
    //...
}


public class MyDerivedClass : MyOtherClassBase, ICalibrable
{

    private bool m_bDisposed = false;

    ~MyDerivedClass()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool bDisposing)
    {
        if (!m_bDisposed) {
            if (bDisposing) {
                //Dispose managed resources
            }
            //Dispose unmanaged resources
        }
        m_bDisposed = true;

        Type baseType = typeof(MyDerivedClass).BaseType;
        if (baseType != null) {
            if (baseType.GetInterface("IDisposable") != null) {
                //If you have no ancestors implementing base.Dispose(...), comment
                //the following line AND uncomment the throw. 
                //
                //This way, if any of your ancestors decide one day to implement 
                //IDisposable you will know about it right away and proceed to 
                //uncomment the base.Dispose(...) in addition to commenting the throw.
                //base.Dispose(bDisposing);
                throw new ApplicationException("Ancestor base.Dispose(...) not called - " 
                                               + baseType.ToString());
            }
        }
    }
}

Donc, je me demande est-il un moyen de l'appel de base.Dispose() automatiquement/conditionnellement à la place?

Plus De Fond

Il existe un autre mécanisme dans l'application où tous les objets sont enregistrés avec une classe principale. La classe vérifie si ils mettent en œuvre IDisposable.
Si oui, ils sont éliminés de façon appropriée par l'application. Cela évite d'avoir le code à l'aide des classes de traiter avec
appelant Dispose() tout autour par eux-mêmes. Ainsi, l'ajout de IDisposable à une classe qui n'a pas d'ancêtre de l'histoire de IDisposable fonctionne encore parfaitement.

Ne pas utiliser le C# finaliseurs (j'.e ~MyDerivedClass()) ils sont non-déterministe et ne peut pas exécuter parfois

OriginalL'auteur Philibert Perusse | 2008-09-16