2012-01-23 17 views
11

Tak więc mam klasę, która jest ogólna i może potrzebować, w ramach jej metody, stworzyć własną instancję z innym typem generycznym, którego typ uzyskuje się poprzez relfekcję .C# Tworzenie nieznanego generycznego typu w czasie wykonywania

Jest to ważne, ponieważ to repozytorium odwzorowuje T na tabelę bazy danych [jest to ORMish, którą piszę] i jeśli klasa reprezentująca T ma kolekcję reprezentującą KOLEJNĄ tabelę, muszę być w stanie ją podać i przekazać do repozytorium [ala Inception].
Zapewniam metodę na wypadek, gdyby łatwiej było zobaczyć problem.

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; 
      } 

Więc podane GenericRepository i chcę dokonać GenericRepository w jaki sposób mogę to zrobić? Linia muszę wymienić coś, co działa jest

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

Jak jest nieruchomość (jeden system typu ' .Collections.Generic') zadeklarowany w twoim kodzie C#? Czy jego argument typu '' jest taki sam jak 'GenericRepository ', który jest właścicielem właściwości? – dasblinkenlight

+0

Nie, w zasadzie jest to zwykły zbiór innej klasy jako własności klasy. tj. Klasa Teacher ma listę klas klas. Repozytorium pobiera klasę nauczyciela i musi również przetworzyć klasę klasy, ale ponieważ naprawdę pobiera T, musi dowiedzieć się, co musi przetworzyć przy użyciu odbicia – Jordan

+0

Tak samo jest właściwość w klasie 'Teacher' zadeklarowana jako' Lista Klasy {/ * getter i/lub setter * /} '? Czy nie działałoby wtedy 'Activator.CreateInstance (Property.GetType())? – dasblinkenlight

Odpowiedz

28

myślę szukasz sposobu 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

Jeśli mogę, mam 1 problem. Nie mogę uzyskać dostępu do żadnej metody dla danego repozytorium. Jeśli uzyskam do niego dostęp przez bezpośrednie okno, w którym jest napisane GenericRepository i robię ? (Repozytorium GenericRepository )) .GetAll() To poprawnie działa, jak mogę poprawnie obsadzić go w kod taki, że nie potrzebuję tego? Oczywiście mogę to zrobić tylko w bezpośrednim oknie, ponieważ znam typ, który reprezentuje. – Jordan

+0

@Jordan, możesz utworzyć nietypowy interfejs 'IRepository' za pomocą metody" GetAll ", która zwraca tablicę obiektów i implementuj jawnie ten interfejs w klasie' GenericRepository '. Lub możesz wywołać metodę dynamicznie za pomocą odbicia, ale jest wolniej ... –

+0

Ah ok. Również zdałem sobie sprawę, jeśli deklaruję go jako dynamiczny zamiast var, który działa – Jordan

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

Spowoduje to utworzenie wystąpienia 'GenericRepository ', ponieważ 'Property .GetType() 'zwraca' RuntimePropertyInfo' ... –

Powiązane problemy