2010-01-13 3 views
5

Lorsque vous appelez typeof (Bar) .GetInterfaces() dans le scénario suivant, la méthode renvoie IFoo et IBar.Rechercher les interfaces implémentées immédiatement sur un type

interface IFoo {}
interface IBar : IFoo {}
class Bar : IBar {}

Est-il possible que je peux trouver que l'interface immédiate (BIRA) sur la barre?

+1

Pourquoi voudriez-vous faire cela? Cela ressemble à un défaut de conception dans votre code;) –

+0

Le tableau retourné est non déterministe. – sduplooy

+0

@Oliver, le système mappe les interfaces aux types de béton. Le problème est qu'un autre type pourrait implémenter IFoo mais nous ne voulons pas associer l'interface IFoo à la classe Bar, mais plutôt à l'interface IBar. – sduplooy

Répondre

12

Non, il n'y a pas d'interface "immédiate" dans le code compilé. Votre classe est efficacement compilée en tant que:

class Bar : IBar, IFoo { } 

et vous ne pouvez pas distinguer entre les deux. La seule chose que vous pouvez faire est de les vérifier tous et de voir si deux interfaces ou plus héritent l'une de l'autre ou non (et même dans ce cas, vous ne pouvez pas vraiment vérifier si l'auteur de la classe a explicitement mentionné le interface de base en code ou non):

static IEnumerable<Type> GetImmediateInterfaces(Type type) 
{ 
    var interfaces = type.GetInterfaces(); 
    var result = new HashSet<Type>(interfaces); 
    foreach (Type i in interfaces) 
     result.ExceptWith(i.GetInterfaces()); 
    return result; 
} 
1
public interface IRoo { } 
public interface ISoo : IRoo { } 
public interface IMoo : ISoo { } 
public interface IGoo : IMoo { } 
public interface IFoo : IGoo { } 
public interface IBar : IFoo { } 
public class Bar : IBar { } 

private void button1_Click(object sender, EventArgs e) { 
    Type[] interfaces = typeof(Bar).GetInterfaces();  
    Type immediateInterface = GetPrimaryInterface(interfaces); 
    // IBar 
} 

public Type GetPrimaryInterface(Type[] interfaces) 
{ 
    if (interfaces.Length == 0) return null; 
    if (interfaces.Length == 1) return interfaces[0]; 

    Dictionary<Type, int> typeScores = new Dictionary<Type, int>(); 
    foreach (Type t in interfaces) 
     typeScores.Add(t, 0); 

    foreach (Type t in interfaces) 
     foreach (Type t1 in interfaces) 
      if (t.IsAssignableFrom(t1)) 
       typeScores[t1]++; 

    Type winner = null; 
    int bestScore = -1; 
    foreach (KeyValuePair<Type, int> pair in typeScores) { 
     if (pair.Value > bestScore) { 
      bestScore = pair.Value; 
      winner = pair.Key; 
     } 
    } 
    return winner; 
} 
+0

Un code intéressant, mais pourquoi 'GetPrimaryInterface' renvoie-t-il seulement un type d'interface? Il semble qu'il faudrait potentiellement retourner plusieurs types d'interface pour être utile. – HappyNomad

0

Cette choisit l'interface avec l'arbre d'héritage le plus long.

typeof(Bar) 
    .GetInterfaces() 
    .OrderByDescending(i => i.GetInterfaces().Length) 
    .FirstOrDefault() 

C'était suffisant pour mon cas d'utilisation.

Questions connexes