62 votes

Détecter si une méthode a été remplacée à l'aide de la réflexion (C #)

Disons que j'ai une classe de base TestBase où je définis une méthode virtuelle TestMe ()

 class TestBase
{
    public virtual bool TestMe() {  }
}
 

Maintenant, j'hérite de cette classe:

 class Test1 : TestBase
{
    public override bool TestMe() {}
}
 

Maintenant, en utilisant Reflection, je dois trouver si la méthode TestMe a été remplacée dans la classe enfant - est-ce possible?

Ce dont j'ai besoin - j'écris un visualiseur de concepteur pour le type "objet" pour montrer toute la hiérarchie de l'héritage et montrer également quelles méthodes virtuelles ont été remplacées à quel niveau.

74voto

Rex M Points 80372

Étant donné le type d' Test1, vous pouvez déterminer si elle a sa propre mise en œuvre de la déclaration de l' TestMe:

typeof(Test1).GetMethod("TestMe").DeclaringType == typeof(Test1)

Si la déclaration est venu à partir d'un type de base, cela permettra d'évaluer la valeur false.

Notez que puisque c'est un test de déclaration, pas de réelle mise en œuvre, ce sera retourne true si Test1 est aussi abstrait et TestMe est abstraite, car Test1 aurait sa propre déclaration. Si vous souhaitez exclure ce cas, ajoutez - && !GetMethod("TestMe").IsAbstract

30voto

ESV Points 4591

Je n'ai pas réussi à faire fonctionner la solution proposée par Ken Beckett . Voici ce sur quoi je me suis installé:

     public static bool IsOverride(MethodInfo m) {
        return m.GetBaseDefinition().DeclaringType != m.DeclaringType;
    }
 

Il y a des tests dans l'essentiel .

27voto

Ken Beckett Points 577

Comme @Ciprian souligné, l'on a accepté la réponse n'est pas complète et conduira à un vilain bug dans votre code si vous l'utilisez comme-est. Son commentaire fournit la solution magique "GetBaseDefinition()", mais il n'y a pas besoin de vérifier les DeclaringType si vous voulez un usage général "IsOverride" check (qui, je pense, a été le point de cette question), juste "methodInfo.GetBaseDefinition() != methodInfo". Ou, à condition qu'une méthode d'extension sur MethodInfo, je pense que cela fera l'affaire:

public static class MethodInfoUtil
{
    public static bool IsOverride(this MethodInfo methodInfo)
    {
        return (methodInfo.GetBaseDefinition() != methodInfo);
    }
}

6voto

Michael Hays Points 2967

Une solution simple qui fonctionnera également pour les membres et les propriétés protégés est la suivante:

 var isDerived = typeof(Test1 ).GetMember("TestMe", 
               BindingFlags.NonPublic 
             | BindingFlags.Instance 
             | BindingFlags.DeclaredOnly).Length == 0;
 

Ceci est une rediffusion de ma réponse ici , qui à son tour avait fait référence à cette question.

2voto

CodesInChaos Points 60274

Une méthode qui fonctionne également dans certains cas non triviaux:

 public bool Overrides(MethodInfo baseMethod, Type type)
{
    if(baseMethod==null)
      throw new ArgumentNullException("baseMethod");
    if(type==null)
      throw new ArgumentNullException("type");
    if(!type.IsSubclassOf(baseMethod.ReflectedType))
        throw new ArgumentException(string.Format("Type must be subtype of {0}",baseMethod.DeclaringType));
    while(type!=baseMethod.ReflectedType)
    {
        var methods=type.GetMethods(BindingFlags.Instance|
                                    BindingFlags.DeclaredOnly|
                                    BindingFlags.Public|
                                    BindingFlags.NonPublic);
        if(methods.Any(m=>m.GetBaseDefinition()==baseMethod))
            return true;
        type=type.BaseType;
    }
    return false;
}
 

Et quelques tests laids:

 public bool OverridesObjectEquals(Type type)
{
    var baseMethod=typeof(object).GetMethod("Equals", new Type[]{typeof(object)});
    return Overrides(baseMethod,type);
}

void Main()
{
    (OverridesObjectEquals(typeof(List<int>))==false).Dump();
    (OverridesObjectEquals(typeof(string))==true).Dump();
    (OverridesObjectEquals(typeof(Hider))==false).Dump();
    (OverridesObjectEquals(typeof(HiderOverrider))==false).Dump();
    (OverridesObjectEquals(typeof(Overrider))==true).Dump();
    (OverridesObjectEquals(typeof(OverriderHider))==true).Dump();
    (OverridesObjectEquals(typeof(OverriderNothing))==true).Dump();
}

class Hider
{
  public virtual new bool Equals(object o)
    {
      throw new NotSupportedException();
    }
}


class HiderOverrider:Hider
{
  public override bool Equals(object o)
    {
      throw new NotSupportedException();
    }
}

class Overrider
{
  public override bool Equals(object o)
    {
      throw new NotSupportedException();
    }
}


class OverriderHider:Overrider
{
  public new bool Equals(object o)
    {
      throw new NotSupportedException();
    }
}

class OverriderNothing:Overrider
{

}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X