2011-05-20 11 views
6

Quiero filtrar objetos en un List<ISeries> usando su tipo, usando OfType <>. Mi problema es que algunos objetos tienen un tipo de interfaz genérico, pero no tienen una interfaz heredada común.

Tengo las siguientes definiciones:Cómo filtrar a todas las variantes de un tipo genérico usando OfType <>

public interface ISeries 
public interface ITraceSeries<T> : ISeries 
public interface ITimedSeries : ISeries 
//and some more... 

Mi lista contiene todos los tipos de ISeries, pero ahora lo que solo son necesarios los ITraceSeries objetos, independientemente de su parámetro de tipo genérico realidad definida, así:

var filteredList = myList.OfType<ITraceSeries<?>>(); //invalid argument! 

¿Cómo puedo hacer eso?

Una solución unfavored sería introducir un tipo ITraceSeries que hereda de ISeries:

public interface ITraceSeries<T> : ITraceSeries 

A continuación, utilice ITraceSeries como filtro. Pero esto realmente no agrega nueva información, sino que solo hace que la cadena de herencia sea más complicada.

Me parece un problema común, pero no encontré información útil sobre SO o la web. ¡Gracias por la ayuda!

+2

Piense en lo que el tipo de retorno de 'myList.OfType' debe ser. –

+0

Debe ser IEnumerable . Pero este es un buen punto, ¿cómo decir eso al método OfType <>? – Marcel

+1

El tipo de devolución de OfType es el mismo que el parámetro de tipo. –

Respuesta

5

Puede utilizar la reflexión para lograrlo:

var filteredList = myList.Where(
    x => x.GetType() 
      .GetInterfaces() 
      .Any(i => i.IsGenericType && (i.GetGenericTypeDefinition() == typeof(ITraceSeries<>)))); 
+0

¡Cosas geniales! Sin embargo, pensé, podría reducir la complejidad ... ¡Ahora mi complejidad está escondida en un espacio remoto, no en la estructura de herencia! :-) – Marcel

+0

¿Puede decirme qué tipo de (ITraceSeries <>) realmente devuelve como tipo? Hasta donde yo sé, las clases genéricas no comparten una clase base común. (Esta fue mi fuente de problemas en primer lugar) – Marcel

+0

@Marcel: 'typeof (ITraceSeries <>)' devuelve un tipo genérico abierto para 'ITraceSeries '. No puede declarar objetos de ese tipo, pero puede usar eso para hacer tipos cerrados como 'ITraceSeries '. –

1
from s in series 
where s.GetType().GetGenericTypeDefinition()==typeof(ITraceSeries<>) 
select s; 
+0

buena idea, pero no va a funcionar exactamente igual que como 'typeof (ITraceSeries ) = typeof (ITraceSeries <>)'!. Arreglado. –

+0

:-) Gran parte de las respuestas son solo ideas: dirección a la solución correcta. Gracias por la corrección. – VikciaR

+0

@Martinho: Eso todavía no funcionará porque 'GetType' devolverá un hormigón, tipo y tiempo de ejecución de ese tipo nunca será' 'ITraceSeries , que será una aplicación concreta de' 'ITraceSeries . Vea mi respuesta para encontrar una solución que, con suerte, cumpla con los requisitos del OP. – LukeH

Cuestiones relacionadas