2012-01-23 47 views
11

Tengo una clase que es genérica y puede necesitar, dentro de un método propio, crear una instancia de sí mismo con un tipo diferente de genérico, que se obtiene a través de la relización .C# Creando un tipo genérico desconocido en tiempo de ejecución

Esto es importante porque este repositorio asigna T a una tabla de base de datos [es un ORMish que estoy escribiendo] y si la clase que representa T tiene una colección que representa OTRA tabla, necesito poder instanciarla y pasarla al repositorio [ala Inception].
Proporciono el método en caso de que sea más fácil ver el problema.

private PropertiesAttributesAndRelatedClasses GetPropertyAndAttributesCollection() 
     { 
    // Returns a List of PropertyAndAttributes 
    var type = typeof(T); 
//For type T return an array of PropertyInfo 

    PropertiesAttributesAndRelatedClasses PAA = new PropertiesAttributesAndRelatedClasses(); 
//Get our container ready 

     PropertyAndAttributes _paa; 
     foreach (PropertyInfo Property in type.GetProperties()) 
//Let's loop through all the properties. 

      {      
     _paa = new PropertyAndAttributes(); 
//Create a new instance each time. 

     _paa.AddProperty(Property); 
//Adds the property and generates an internal collection of attributes for it too 

     bool MapPropertyAndAttribute = true; 
     if (Property.PropertyType.Namespace == "System.Collections.Generic") 
    //This is a class we need to map to another table 
       { 
        PAA.AddRelatedClass(Property); 
       //var x = Activator.CreateInstance("GenericRepository", Property.GetType().ToString()); 
        } 
        else 
        { 
         foreach (var attr in _paa.Attrs) 
         { 
          if (attr is IgnoreProperty) 
//If we find this attribute it is an override and we ignore this property. 
          { 
           MapPropertyAndAttribute = false; 
           break; 
          } 
         } 
        } 
        if (MapPropertyAndAttribute) 
         PAA.AddPaa(_paa); 
      //Add this to the list. 
       } 
       return PAA; 
      } 

Así da GenericRepository, y quiero hacer una GenericRepository ¿cómo voy a hacer esto? La línea tengo que sustituir con algo que funciona es

//     var x = Activator.CreateInstance("GenericRepository", Property.GetType().ToString()); 
+0

¿Cómo es la propiedad (la de tipo 'Sistema .Collections.Generic') declarado en su código C#? ¿Es su argumento de tipo '' el mismo que el del 'GenericRepository ' que posee la propiedad? – dasblinkenlight

+0

No, básicamente es solo una colección genérica de otra clase como propiedad de una clase. es decir, una clase de profesor tiene una lista de clases de clases. El repositorio obtiene la clase de profesor y también debe procesar la clase de clases, pero como realmente está obteniendo T tiene que averiguar qué tiene que procesar utilizando la reflexión – Jordan

+0

. Así es la propiedad en la clase 'Profesor' declarada como 'Lista Clases {/ * getter y/o setter * /} '? ¿No funcionaría 'Activator.CreateInstance (Property.GetType())'? – dasblinkenlight

Respuesta

28

Creo que está buscando el método MakeGenericType:

// Assuming that Property.PropertyType is something like List<T> 
Type elementType = Property.PropertyType.GetGenericArguments()[0]; 
Type repositoryType = typeof(GenericRepository<>).MakeGenericType(elementType); 
var repository = Activator.CreateInstance(repositoryType); 
+0

Si puedo, me estoy encontrando con 1 problema. No puedo acceder a ningún método para el repositorio dado. Si accedo a él a través de la ventana inmediata donde hizo decir GenericRepository y hago ? ((GenericRepository repository) .GetAll() Esto funciona correctamente, ¿cómo puedo lanzarlo correctamente en el código tal que no necesito esto? Obviamente solo puedo hacerlo en la ventana inmediata porque sé el tipo que representa. – Jordan

+0

@Jordan, puede crear una interfaz 'IRepository' no genérica con un método' GetAll' que devuelve una matriz de objetos, e implementar esta interfaz explícitamente en la clase 'GenericRepository '. O puede llamar al método de forma dinámica mediante la reflexión, pero es más lento ... –

+0

Ah ok. También me di cuenta si lo declaro como dinámico en lugar de var que funciona – Jordan

4
Activator.CreateInstance(typeof(GenericRepository<>).MakeGenericType(new Type[] { Property.GetTYpe() })) 
+1

Esto creará una instancia de 'GenericRepository ', ya que 'Property .GetType() 'devuelve' RuntimePropertyInfo' ... –

Cuestiones relacionadas