2010-09-16 2 views
0

Étant donné une séquence d'assemblages avec des classes, par exemple.Utilisation de LINQ pour trouver la classe qui se trouve au bas de la chaîne d'héritage

AssemblyA 
    Customer 
    AssemblyB 
    Customer : AssemblyA.Customer 
    AssemblyC 
    Customer : AssemblyB.Customer 

Étant donné le nom (non pris en charge namespace) client, puis-je utiliser LINQ pour interroger contre la séquence d'ensembles pour trouver le client au bas de la chaîne d'héritage (AssemblyC.Customer dans ce cas) ?

+0

Cette question n'est pas claire. Essayez-vous d'utiliser LINQ pour interroger les métadonnées de réflexion sur les classes 'Customer' ou l'utilisez-vous pour interroger une sorte de collection d'objets' Customer'? – LBushkin

+1

Et si c'est un arbre qui s'embranche? – recursive

+0

@LBushkin: Tout ce que je veux, c'est le type qui se trouve en bas de la chaîne d'héritage à partir d'une séquence d'assemblages. Un objet System.Type pour être précis. – Marcus

Répondre

1
IEnumerable<Assembly> assemblies = ... 
Assembly assemblyA = ... 

// Since you say the only fact you wish to use about the class is that it 
// is named 'Customer' and it exists in Assembly A, this is just about the 
// only way to construct the Type object. Pretty awful though... 
Type customerType = assemblyA.GetTypes() 
          .Single(t => t.Name == "Customer");  

// From all the types in the chosen assemblies, find the ones that subclass 
// Customer, picking the one with the deepest inheritance heirarchy. 
Type bottomCustomerType = assemblies.SelectMany(a => a.GetTypes()) 
            .Where(t => t.IsSubclassOf(customerType)) 
            .OrderByDescending(t => t.GetInheritanceDepth()) 
            .First(); 
... 

public static int GetInheritanceDepth(this Type type) 
{ 
    if (type == null) 
     throw new ArgumentNullException("type"); 

    int depth = 0; 

    // Keep walking up the inheritance tree until there are no more base classes. 
    while (type != null) 
    { 
     type = type.BaseType; 
     depth++; 
    } 

    return depth; 
} 
+0

Nice, ça marche. La raison pour laquelle j'ai posé cette question était de voir si quelqu'un pourrait construire une belle requête LINQ pour le faire, ma solution actuelle ressemble beaucoup à la vôtre. – Marcus

+0

Pas exactement ce dont j'avais besoin, mais proche. Dans ce cas, je voulais juste savoir si un type dérivé d'un certain type dans le même assemblage. Votre réponse a aidé: public static bool CanTypeCastTo (ce Type derivedType, Type baseType) { if (baseType == nullType) throw new ArgumentNullException ("baseType"); t = derivedType.BaseType; bool result = t == baseType; while (t! = Null &&! Résultat) { t = t.BaseType; résultat = t == baseType || t.IsSubclassOf (baseType);} return result; } 'Merci encore pour votre réponse. – fourpastmidnight

0

La première question est de savoir comment déterminer les ensembles à rechercher. System.Reflection.Assembly fournit un certain nombre de méthodes pour répertorier certains types d'assemblages - par exemple GetReferencedAssemblies() trouvera des assemblys référencés par un assembly donné - utile si vous avez Assembly C (qui identifie B et A), mais pas si vous venez avoir l'Assemblée A (qui n'en fait aucun). Vous pouvez également scanner le disque, ou d'autres méthodes, selon vos besoins.

Une fois que vous avez déterminé comment itérer assemblées, utilisez la technique de cet article à trouver des classes qui dérivent de la classe en question: Discovering derived types using reflection

appliquer cette logique récursive jusqu'à la fin de l'arbre. L'intervenant sur votre question a raison - l'arbre peut avoir plusieurs branches. Je ne sais pas pourquoi vous voudriez utiliser Linq pour faire ceci - Linq ne semble pas construit pour ce type de question. Je n'ai personnellement trouvé aucun moyen de faire des opérations de récursion ou de file d'attente à l'intérieur de Linq. J'utiliserais juste C# ou VB déclarations simples pour cela plutôt que Linq.

Questions connexes