2010-02-21 13 views
5

Mi primer objetivo es filtrar los tipos basados ​​en una interfaz específica con un genérico.Cómo reflejar los tipos que tienen una interfaz de genérico, y obtener ese tipo de genérico

Mi segundo objetivo es obtener el tipo del parámetro genérico en sí.

public UserService : IUserService, IDisposable, IExportableAs<IUserService> 
{ 
    ... 
} 

no puedo asumir la estructura de la clase, sus interfaces (o ninguna en absoluto) o similar. Lo único que sé es que estoy apuntando a ExportableAs<T> desde mi ensamblado compartido que se utilizó para crear este complemento. Pero aún así, debo registrar el tipo dinámicamente.

Por lo tanto, estoy usando una interfaz genérica para marcar el tipo para exportar. En este caso, es IUserService. Estoy haciendo esto suponiendo que alguna consulta ingeniosa de Linq puede darme lo que quiero. Pero, estoy teniendo un pequeño problema.

Esto es lo que tengo hasta ahora:

assembly.GetTypes() 
    .Where(t => t.GetInterfaces().Any(i => 
       i.IsGenericType && 
       i.GetGenericTypeDefinition() == typeof(IExportableAs<>)) 
      ).ToList() 
    .ForEach(t => _catalogs.Add(
      new ComposablePart() 
      { 
       Name = t.FullName, 
       Type = t // This is incorrect 
      }) 
     ); 

Esto está funcionando, pero noto el comentario anterior de "Esto es incorrecto". Este tipo es la clase derivada de UserService.

Lo que necesito en mi resultado final son:

  • El tipo genérico pasan al IExportableAs<T> (IUserService en este caso)
  • El tipo de clase derivada (en este caso, UserService)

Esta pregunta obtuvo un buen voto positivo ya que me acercó (como se puede ver arriba): How to determine if a type implements a specific generic interface type Pero, tengo que ir un paso más allá en la búsqueda de ese tipo genérico.

Siéntase libre de mangle my linq arriba.

¡Gracias de antemano!

Respuesta

4

Tienes que

assembly.GetTypes().SelectMany(t => t.GetInterfaces(), (t, i) => new { t, i }) 
    .Where(ti => ti.i.IsGenericType && 
       ti.i.GetGenericTypeDefinition() == (typeof(IExportableAs<>))) 
    .Select(ti => new ComposablePart() { 
     Name = ti.t.FullName, 
     Type = ti.i.GetGenericArguments()[0] 
    }); 

[Editar] En mi entusiasmo, yo no dejo mi programa de pruebas de funcionamiento el tiempo suficiente para lanzar una excepción en la interfaz que no era genérico. Pensé que .NET Framework había sido especialmente inteligente allí. Código corregido ahora que sé que no es.

+0

Interesante. Usando un tipo anónimo para crear un objeto. Esto tiene una promesa. +1 – eduncan911

+0

Sí, eso fue todo. Sin embargo, tenga en cuenta que está creando un segundo tipo anónimo en la cláusula Select(). Debería ser: '.Seleccione (ti => nuevo ComposablePart() {Name = ti.t.FullName, Type = ti.i.GetGenericArguments() [0]});' De lo contrario, no se convertirá en un conocido escriba en una ToList(). – eduncan911

+0

Aunque me preocupa el índice 'GetGenericTypeDefinition() [0]'. Esto me limita a solo 1 'IExportableAs <>' ¿correcto? – eduncan911

Cuestiones relacionadas