2009-09-22 6 views
3

La classe System.Type fournit une méthode GetInterfaces() qui "obtient toutes les interfaces implémentées ou héritées par le type actuel". Le problème est que "La méthode GetInterfaces ne renvoie pas les interfaces dans un ordre particulier, tel que l'ordre alphabétique ou de déclaration.Votre code ne doit pas dépendre de l'ordre dans lequel les interfaces sont retournées, car cet ordre varie". Dans mon cas, cependant, je dois isoler et exposer (via WCF) uniquement les interfaces feuille de la hiérarchie d'interface, c'est-à-dire les interfaces qui ne sont pas héritées par d'autres interfaces dans cette hiérarchie. Par exemple, considérons la hiérarchie suivanteRécupération des interfaces de feuille d'un type

interface IA { } 
interface IB : IA { } 
interface IC : IB { } 
interface ID : IB { } 
interface IE : IA { } 
class Foo : IC, IE {} 

interfaces feuille de Foo sont IC et IE, alors que GetInterfaces() renverra toutes les 5 interfaces (IA..IE). Une méthode FindInterfaces() est également fournie, vous permettant de filtrer les interfaces susmentionnées en utilisant un prédicat de votre choix.

Ma mise en œuvre actuelle est donnée ci-dessous. C'est O (n^2) où n est le nombre d'interfaces que le type implémente. Je me demandais s'il y avait une façon plus efficace et/ou efficace de le faire.

private Type[] GetLeafInterfaces(Type type) 
    { 
     return type.FindInterfaces((candidateIfc, allIfcs) => 
     { 
      foreach (Type ifc in (Type[])allIfcs) 
      { 
       if (candidateIfc != ifc && candidateIfc.IsAssignableFrom(ifc)) 
        return false;  
      } 
      return true; 
     } 
     ,type.GetInterfaces()); 
    } 

Merci à l'avance

Répondre

3

Je ne pense pas que vous trouverez une solution simple à cela. Votre problème est qu'à la fin, Foo implémente réellement toutes les interfaces, indépendamment de leur hiérarchie d'héritage interne. Si vous examinez Foo en utilisant Ildasm ou un outil similaire, cela devient évident. Considérez le code suivant:

interface IFirst { } 
interface ISecond : IFirst { } 
class Concrete : ISecond { } 

résultant du code IL (sous-évaluées de Ildasm):

.class private auto ansi beforefieldinit MyNamespace.Concrete 
     extends [mscorlib]System.Object 
     implements MyNamespace.ISecond, 
        MyNamespace.IFirst 
{ 
    .method public hidebysig specialname rtspecialname 
      instance void .ctor() cil managed 
    { 
    // Code size  7 (0x7) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: call  instance void [mscorlib]System.Object::.ctor() 
    IL_0006: ret 
    } // end of method Concrete::.ctor 

} // end of class MyNamespace.Concrete 

Comme vous pouvez le voir, à ce niveau il n'y a pas de différence dans la relation entre Concrete et les deux interfaces .

+0

Merci! Peut-être que ma fonction GetLeafInterfaces() pourrait être utile à quelqu'un dans le futur, alors –