2009-11-12 3 views
0

permet de dire que j'ai un arbre d'héritage d'interfaces:Détermination de l'interface enfant le plus proche à une classe

IParent> iChild> IGrandChild

Comment puis-je:

  1. Trouvez une classe qui implémente IParent
  2. Détermine l'ancêtre le plus proche de la classe qui est également un enfant de IParent.

Par exemple:

var myClass = FindImplementor<IParent>(); 
var myInterface = ClosestAncestor<IParent, myclass>(); 

Je ne cherche pas à créer des fonctions qui correspondent aux signatures ci-dessus. C'était juste pour clarifier.

Les descendants d'IParent ainsi que la classe d'implémentation se trouvent dans un assembly chargé dynamiquement. Je ne suis pas sûr si cela ferait une différence ou non.

+0

C# prend en charge l'héritage multiple des interfaces. Disons qu'il y a deux intefaces héritant de IParent: IChild1 et IChild2. Que se passe-t-il si une classe implémente IChild1 et IChild2? –

+0

L'ancien diamant d'héritage multiple. Dans mon scénario, je n'utilise pas cette fonctionnalité.Toutes mes classes implémentant plusieurs interfaces implémentent des interfaces sans ancêtre commun. –

+0

Même s'il n'y a pas de "diamants", vous devrez toujours parcourir l'arbre d'héritage de l'interface pour trouver IParent. Les fonctions récursives viennent à l'esprit pour traverser un arbre pour trouver quelque chose. –

Répondre

1

Vous pouvez utiliser le mot-clé en tant que et vérifier null.

Exemple:

var someObject = GetMeSomething(); //returns some IParent/IChild/IGrandChild 

if ((someObject as IParent) != null) 
    if ((someObject as IChild) != null) 
    { 
     if ((someObject as IGrandChild) != null) 
     { 
      //you have an IGrandChild 
     } 
     else 
     { 
      //you have an IChild 
     } 
    } 
    else 
    { 
     //you have an IParent 
    } 
} 
//you have something other than your interface hierarchy 

Je ne suis pas vraiment aimer l'idée, en fait, mais il est ce qui est venu à l'esprit. Il y a un certain nombre de problèmes à essayer d'identifier la chaîne. Plusieurs chaînes de mise en œuvre viennent à l'esprit.

1

Pour obtenir "Implémenteurs" de IParent

var classes = Assembly.GetTypes(); 
var parentImplementors = classes.Where(x => x.IsAssignableFrom(typeof(IParent))); 

Il n'y a pas de manière simple et parfaitement travailler pour obtenir le "closest ancestors" of an interface.

0

J'espère bien compris la question :)

ClosestAncestor

public Type ClosestAncestor<IParent, Class>() 
{ 
    return ClosestAncestor<IParent>(typeof(Class)); 
} 

public Type ClosestAncestor<IParent>(Type typeOfClass) 
{ 
    var baseType = typeOfClass.BaseType; 
    if(typeOfClass.GetInterfaces().Contains(typeof(IParent)) && 
     ! baseType.GetInterfaces().Contains(typeof(IParent))) 
    { 
     return typeOfClass; 
    } 

    return ClosestAncestor<IParent>(baseType); 
} 

Comme on peut le voir, le code suppose la classe implémente IParent (sinon - bug ...).

échantillon de test:

public interface I {} 
public class A {} 
public class B : A, I {} 
public class C : B {} 

[Test] 
public void ClosestAncestorTest() 
{ 
    Type closestAncestor = ClosestAncestor<I,C>(); 
    Assert.AreEqual(typeof(B), closestAncestor); 
} 

FindImplementor

Chargement premier type qui implémente une interface:

public Type FindImplementor<T>() 
{ 
    return AppDomain.CurrentDomain.GetAssemblies() 
     .SelectMany(assembly => assembly.GetTypes()) 
     .FirstOrDefault(type => type.GetInterfaces().Contains(typeof(T))); 
} 

Je supposais l'ensemble est chargé dans le domaine App et les recherches de code partout pour un exécutant. Si un seul assemblage est intéressant, vous pouvez obtenir uniquement ces types d'assemblage (comme dans la réponse de Guillaume)

+0

Votre ClosestAncestor échouera lorsque Type et BaseType implémenteront l'interface IParent. – Guillaume

+0

@Guillaume, tu as raison, c'est un bug :) – Elisha