10
votes

Comment vérifier si un type .NET implémente une certaine interface .NET abstraitement?

J'ai un type et une interface et j'ai besoin de vérifier que le type implémente l'interface abstraite.

J'ai défini pour écrire un code de force brute à l'aide de la réflexion et c'est assez moche.

Je me demande s'il y a une meilleure façon que la mise en œuvre de la force brute que je fais maintenant.

Toute idée?

Merci.

Edit < / strong>

n'a pas encore vérifié la mise en œuvre, mais le code brut de la force brute ressemble à ceci: xxx

sans la compilation, je vois déjà un problème Avec des propriétés, que le code doit vérifier si l'interface définit Getter et / ou Setter et vérifie la (les) méthode (s) de droite) au lieu d'assumer aveuglément le getter. Quoi qu'il en soit, comme on peut le voir, le code est assez terne. Je me demande s'il y a une meilleure façon ...

EDIT 2

  • Je tiens à souligner que ce n'est qu'un projet de mise en œuvre, cela fonctionne pour des cas simples et il est cassé pour des celles plus complexes, comme lorsqu'il existe des surcharges de méthode ou une méthode renommée (je ne sais pas VB, donc je n'ai pas fait même penser que c'était possible). Mais il souligne mon point que cela exige beaucoup de travail de le faire correctement.
  • Pourquoi voudrais-je vouloir une telle chose? Nous devons créer des types de manière dynamique en utilisant la réflexion.MIT en fonction de certaines métadonnées acquises dynamiquement acquises. Le type dynamique généré implémente une certaine interface, disons IdynnamicObject et peut dériver de certains types d'ancêtres. Ce type d'ancêtre est statiquement compilé. Jusqu'à récemment, le type d'ancêtre n'était pas autorisé à mettre en œuvre l'interface IdynamicObject. Compte tenu d'une instance du type dynamique, il fallait explicitement le jeter à IdynnamicObject afin d'accéder à ses méthodes (rappelez-vous que le type dynamique généré implémente l'interface). Je voudrais éliminer ces moulages explicites. La seule façon de le faire est de laisser le type d'ancêtre implémenter l'interface idynamicObject. Toutefois, la mise en œuvre doit être tout abstraite, qui est vérifiée par le code de création de type dynamique. Voila.

8 commentaires

"Code de force brute utilisant la réflexion" - pouvez-vous le poster?


Que voulez-vous dire exactement lorsque vous dites que le "type implémente l'interface abstraite"?


OK, quelques minutes pour vous assurer que cela fonctionne du tout.


Par "abstraitement", je veux dire que chaque membre d'interface est implémenté à l'aide du mot clé abstrait.


Vous vous demandez simplement, mais pourquoi auriez-vous jamais besoin de vérifier si une classe implémente tous les membres de l'interface avec le mot clé abstrait?


Mes pensées exactement. Vous n'allez jamais rencontrer une instance d'une telle classe, car c'est une classe abstraite par définition.


Outre d'autres choses, votre approche de force brute est généralement fausse, car une méthode de classe publique mettant en œuvre une interface n'a pas besoin d'avoir le même nom. Pensez à VB: Public Mustoverride Sub FOO () implémente ibar.bar .


À moins que je ne manque rien, cela ne fonctionnera pas du tout parce que vous ne vérifiez que le nom au lieu de la signature de la méthode complète.


4 Réponses :


29
votes

Vous pouvez déterminer si un type implémente une interface particulière en utilisant Type.ISAssignABLABLEFROM :

public static bool IsAbstractOf<TInterface>(this Type type)
{
    var map = type.GetInterfaceMap(typeof(TInterface));
    foreach (var info in map.TargetMethods)
    {
        if (!info.IsAbstract)
        {
            return false;
        }
    }
    return true;
}


4 commentaires

On sait que le type implémente l'interface. Ce dont j'ai besoin, c'est si la mise en œuvre est tout abstraite.


@Mark Il n'y a aucun moyen de savoir sans réfléchir chaque membre à voir s'il est abstrait.


Je soupçonne ça. Mais peut-être qu'il y a des astuces liées à la réflexion que je ne suis pas au courant.


Merci, l'utilisation de l'intefacap est l'astuce que je cherchais.



1
votes

La réponse de Rex M est correcte en général, mais si votre type est un paramètre de type, vous pouvez également faire:

class Foo<T> where T : IWhatever {
    // Do your thing, secure in the knowledge that T implements IWhatever
}


1 commentaires

On sait que le type implémente l'interface. Ce dont j'ai besoin, c'est si la mise en œuvre est tout abstraite.



1
votes
public static bool IsAbstractInterfaceImplementation(Type someType, Type someInterface)
{
    return someType.IsAbstract && someInterface.IsAssignableFrom(someType);
}

1 commentaires

Cela ne détermine que si la classe est abstraite, non si certaines méthodes sont abstraites.



0
votes

Vous ne pouvez pas utiliser les noms des membres. Parce qu'il n'y a aucune raison d'assumer, que le nom d'un membre vous indique quoi que ce soit sur l'interface membre de l'interface. La réflexion vous fournit des moyens de voir quelle méthode implémente l'une de l'interface, cependant.

Voici un extrait qui retournerait toute la méthode sur un type donné qui ne sont implémentés que de manière abstraite. P>

static IEnumerable<MethodInfo> GetAbstractImplementations(this Type implementingType, Type interfaceType)
{
    if(!interfaceType.IsInterface)
        throw new ArgumentException(interfaceType.FullName + " is not an interface.");
    if(implementingType.IsInterface)
        throw new ArgumentException(interfaceType.FullName + " is an interface.");

    if(!interfaceType.IsAssignableFrom(implementingType))
        throw new ArgumentException(implementingType.FullName + " does not implement " + interfaceType.FullName + ".");

    var mapping = implementingType.GetInterfaceMap(interfaceType);
    return from m  in mapping.TargetMethods 
           where m.IsAbstract
           select m;
}

public static bool IsAbstractInterfaceImplementationOf(this Type implementingType, Type interfaceType)
{
    return implementingType.GetAbstractImplementations(interfaceType).Any();
}


0 commentaires