2011-06-21 15 views
6

Estoy intentando escribir un método utilizando reflection para devolver todas las clases que son subclases de una clase que usa genéricos, sin estar limitado por el tipo genérico Entonces, por ejemplo, en EF quiero encontrar todas las clases de mapeo. Las clases están configurados como:¿Cómo puedo usar el reflejo para devolver todas las clases subclases desde un genérico, sin dar un tipo genérico específico?

public class clientMap : EntityTypeConfiguration<Client> {} 

Quiero encontrar todas las clases en mi asamblea que es una subclase de de EntityTypeConfiguration<T>, sin especificar Client como T específicamente. Quiero devolver la configuración del tipo de entidad para todas las clases en mi aplicación sin hardcoding.

Sin genéricos me gustaría recorrer los tipos en el conjunto, compruebe si type.IsSubclassOf(typeof(BaseClass)), sin embargo, no estoy seguro de cómo hacerlo cuando se trata de genéricos.

+2

Duplicar ? http://stackoverflow.com/questions/457676/c-reflection-check-if-a-class-is-derived-from-a-generic-class –

+0

Ah, no vi eso, gracias – KallDrexx

Respuesta

10

Creo que desea algo como esto:

static class TypeExtensions { 
    public static bool IsDerivedFromOpenGenericType(
     this Type type, 
     Type openGenericType 
    ) { 
     Contract.Requires(type != null); 
     Contract.Requires(openGenericType != null); 
     Contract.Requires(openGenericType.IsGenericTypeDefinition); 
     return type.GetTypeHierarchy() 
        .Where(t => t.IsGenericType) 
        .Select(t => t.GetGenericTypeDefinition()) 
        .Any(t => openGenericType.Equals(t)); 
    } 

    public static IEnumerable<Type> GetTypeHierarchy(this Type type) { 
     Contract.Requires(type != null); 
     Type currentType = type; 
     while (currentType != null) { 
      yield return currentType; 
      currentType = currentType.BaseType; 
     } 
    } 
} 

Estas pruebas pasan:

class Foo<T> { } 
class Bar : Foo<int> { } 
class FooBar : Bar { } 

[Fact] 
public void BarIsDerivedFromOpenGenericFoo() { 
    Assert.True(typeof(Bar).IsDerivedFromOpenGenericType(typeof(Foo<>))); 
} 

[Fact] 
public void FooBarIsDerivedFromOpenGenericFoo() { 
    Assert.True(typeof(FooBar).IsDerivedFromOpenGenericType(typeof(Foo<>))); 
} 

[Fact] 
public void StringIsNotDerivedFromOpenGenericFoo() { 
    Assert.False(typeof(string).IsDerivedFromOpenGenericType(typeof(Foo<>))); 
} 
+0

¿Qué debería 'abrirGenericType' estar en el código real? 'EntityTypeConfiguration <>' o debe algo estar entre paréntesis? – KallDrexx

+0

Para su caso, 'typeof (EntityTypeConfiguration <>)'. Tenga en cuenta que el código y las pruebas lo aclaran. – jason

+1

Funciona espectacularmente :) – KallDrexx

0

por lo que yo entendía su caso la siguiente debería ser suficiente

type.BaseType != null && 
type.BaseType.MetadataToken == typeof(EntityTypeConfiguration<>).MetadataToken 
Cuestiones relacionadas