2010-01-13 15 views
5

Al llamar typeof (Bar) .GetInterfaces() en la siguiente situación, el método devuelve IFoo e IBar.Encuentra las interfaces implementadas inmediatamente en un tipo

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

¿Hay una manera que puedo encontrar sólo la interfaz inmediata (IBar) sobre el Bar?

+1

¿Por qué le gustaría hacer eso? Me parece una falla de diseño en tu código;) –

+0

La matriz devuelta no es determinista. – sduplooy

+0

@Oliver, el sistema asigna interfaces a tipos concretos. El problema es que otro tipo podría estar implementando IFoo pero no queremos asociar la interfaz IFoo con la clase Bar, sino con la interfaz IBar. – sduplooy

Respuesta

12

No, no existe la interfaz "inmediata" en el código compilado. Su clase se compila efectivamente como:

class Bar : IBar, IFoo { } 

y no puede distinguir entre los dos. Lo único que podría hacer es verificarlos a todos y ver si dos o más de las interfaces se heredan o no (e incluso en ese caso, no se puede verificar si el autor de la clase ha mencionado explícitamente el interfaz base o codificada):

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

Código de aspecto interesante, pero ¿por qué 'GetPrimaryInterface' devuelve solo un tipo de interfaz? Parece que necesitaría devolver potencialmente varios tipos de interfaz para ser útil. – HappyNomad

0

Este escoge la interfaz con el árbol de herencia más larga.

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

Era suficiente para mi caso de uso.

Cuestiones relacionadas