Pregunta

El System.Type clase proporciona un GetInterfaces método () que "recibe todas las interfaces implementadas o heredada por el tipo actual". El problema es que "El método GetInterfaces no devuelve las interfaces en un orden determinado, como por orden alfabético o declaración. El código no debe depender del orden en que se devuelven las interfaces, ya que el orden varía". En mi caso, sin embargo, que necesito para aislar y exponer (a través de WCF) sólo las interfaces de la hoja de la jerarquía de la interfaz, que es interfaces que no son heredados por otras interfaces de la jerarquía. Por ejemplo, considere la siguiente jerarquía

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

interfaces de hoja de Foo son IC y IE, mientras que GetInterfaces () devolverá los 5 interfaces (IA..IE). También se proporciona el método A FindInterfaces (), lo que permite filtrar las interfaces antes mencionadas utilizando un predicado de su elección.

Mi implementación actual es la siguiente. Es O (n ^ 2) donde n es el número de interfaces de los de tipo implementos. Me preguntaba si había una manera más elgant y / o eficiente de hacerlo.

    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());
    }

Gracias de antemano

¿Fue útil?

Solución

No creo que se encuentra una solución simple para esto. Su problema es que, al final, Foo efectivamente en marcha todas las interfaces , independientemente de su jerarquía de herencia interna. Si se examina el uso de Foo Ildasm o alguna herramienta similar esto se hace evidente. Considere el siguiente código:

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

El código IL resultante (objeto de dumping 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

Como se puede ver, en este nivel no hay diferencia en la relación entre Concrete y las dos interfaces.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top