Recuperando las interfaces de las hojas de un tipo
-
12-09-2019 - |
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
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.