Usando la reflexión, ¿cómo puedo obtener todos los tipos que implementan una interfaz con C # 3.0 / .NET 3.5 con el menor código y minimizando las iteraciones?
Esto es lo que quiero volver a escribir:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
Respuestas:
El mío sería esto en c # 3.0 :)
Básicamente, la menor cantidad de iteraciones siempre será:
fuente
.Where(p => type.IsAssignableFrom(p) && !p.IsInterface);
para filtrarla (op.IsClass
).List<string>
no se implementa,IEnumerable<object>
pero este método devolverá verdadero en .Net 4.0 debido a la covarianza, que de hecho es incorrecta. La respuesta correcta está aquí.Where(p => type.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract
Esto funcionó para mí. Recorre las clases en bucle y comprueba si están derivadas de myInterface
fuente
Para buscar todos los tipos en un ensamblaje que implementan la interfaz IFoo:
Tenga en cuenta que la sugerencia de Ryan Rinaldi era incorrecta. Devolverá 0 tipos. No puedes escribir
porque type es una instancia de System.Type y nunca será de tipo IFoo. En cambio, verifica si IFoo es asignable desde el tipo. Eso obtendrá los resultados esperados.
Además, la sugerencia de Adam Wright, que actualmente está marcada como la respuesta, también es incorrecta y por la misma razón. En tiempo de ejecución, verá que regresan 0 tipos, porque todas las instancias de System.Type no fueron implementadores de IFoo.
fuente
Aprecio que esta es una pregunta muy antigua, pero pensé que agregaría otra respuesta para futuros usuarios, ya que todas las respuestas hasta la fecha usan alguna forma de
Assembly.GetTypes
.Si bien GetTypes () realmente devolverá todos los tipos, no necesariamente significa que podría activarlos y, por lo tanto, podría arrojar a
ReflectionTypeLoadException
.Un ejemplo clásico para no poder activar un tipo sería cuando el tipo devuelto es
derived
debase
perobase
se define en un ensamblaje diferente del dederived
, un ensamblaje al que el ensamblado que llama no hace referencia.Entonces digamos que tenemos:
Si en
ClassC
cuál está adentroAssemblyC
, entonces hacemos algo según la respuesta aceptada:Entonces arrojará un
ReflectionTypeLoadException
.Esto se debe a que sin una referencia a
AssemblyA
enAssemblyC
que no sería capaz de:En otras palabras,
ClassB
no se puede cargar, que es algo que la llamada a GetTypes comprueba y lanza.Entonces, para calificar de forma segura el conjunto de resultados para los tipos cargables, según este artículo de Phil Haacked Obtener todos los tipos en un ensamblaje y el código Jon Skeet, en su lugar, haría algo como:
Y entonces:
fuente
CreateInstance
para todos ellos, y se produjo una excepción cuando intentaba crear la interfaz real (lo que me confundió por un tiempo cuando pensé que la interfaz real estaba fuera del camino en esta solución). Entonces cambié el código aGetLoadableTypes(assembly).Where(interfaceType.IsAssignableFrom).Where(t => !(t.Equals(interfaceType))).ToList();
.Otras respuestas aquí usan
IsAssignableFrom
. También puede usarFindInterfaces
desde elSystem
espacio de nombres, como se describe aquí .Aquí hay un ejemplo que verifica todos los ensamblajes en la carpeta del ensamblaje que se está ejecutando actualmente, buscando clases que implementen una determinada interfaz (evitando la claridad de LINQ).
Puede configurar una lista de interfaces si desea hacer coincidir más de una.
fuente
recorrer todos los ensamblajes cargados, recorrer todos sus tipos y verificar si implementan la interfaz.
algo como:
fuente
Esto funcionó para mí (si lo desea, podría excluir los tipos de sistema en la búsqueda):
fuente
Edición: acabo de ver la edición para aclarar que la pregunta original era para la reducción de iteraciones / código y eso está muy bien como ejercicio, pero en situaciones del mundo real querrás la implementación más rápida, independientemente de lo genial que se ve el LINQ subyacente.
Aquí está mi método Utils para iterar a través de los tipos cargados. Maneja clases regulares así como interfaces, y la opción excludeSystemTypes acelera enormemente si está buscando implementaciones en su propia base de código / de terceros.
No es bonito, lo admito.
fuente
excludeSystemTypes
dos veces en unaif
?Otra respuesta no funcionaba con una interfaz genérica .
Este sí, simplemente reemplaza typeof (ISomeInterface) por typeof (T).
Entonces con
obtenemos todas las asambleas
se utiliza para excluir la interfaz y los abstractos y
tenerlos en una lista.
fuente
No hay una manera fácil (en términos de rendimiento) de hacer lo que quieres hacer.
Reflection funciona con ensamblajes y tipos principalmente, por lo que tendrá que obtener todos los tipos del ensamblaje y consultarlos para obtener la interfaz correcta. Aquí hay un ejemplo:
Eso le proporcionará todos los tipos que implementan IMyInterface en el ensamblado MyAssembly
fuente
Aún mejor al elegir la ubicación de montaje. Filtre la mayoría de los ensamblajes si sabe que todas sus interfaces implementadas están dentro del mismo ensamblado.
Por Can Bilgin
fuente
El método OfType Linq se puede usar exactamente para este tipo de escenarios:
https://docs.microsoft.com/fr-fr/dotnet/api/system.linq.enumerable.oftype?view=netframework-4.8
fuente
Ya hay muchas respuestas válidas, pero me gustaría agregar otra implementación como una extensión de Tipo y una lista de pruebas unitarias para demostrar diferentes escenarios:
Este algoritmo admite los siguientes escenarios:
fuente
fuente
Tengo excepciones en el código linq, así que lo hago de esta manera (sin una extensión complicada):
fuente
Puede usar LINQ para obtener la lista:
Pero realmente, ¿eso es más legible?
fuente