c# Creating an unknown generic type at runtime
Solution 1
I think you're looking for the MakeGenericType
method:
// 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);
Solution 2
Activator.CreateInstance(typeof(GenericRepository<>).MakeGenericType(new Type[] { Property.GetTYpe() }))
Jordan
I was a software developer for UPS in another life [1999-2001]. I quit to get my degree in Software Engineering and Psychology I really enjoy developing software. Especially database driven things. Currently a bit over my head making a site using ASP.NET/C#, XML, XSLT, javascript/ajax/json, SQL 2008R2. It is my passion to create things that are extremely fast and efficient despite the fact that the solutions might not be simple.
Updated on July 09, 2022Comments
-
Jordan almost 2 years
So I have a class that is a generic and it may need to, inside a method of its own, create an instance of itself with a different kind of generic, whose type is obtained through reflection.
This is important because this Repository maps
T
to a database table [it's an ORMish I am writing] and if the class that representsT
has a collection representing ANOTHER table I need to be able to instance that and pass it to the repository [ala Inception].
I'm providing the method in case it makes it easier to see the 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 //Let's loop through all the properties. PropertyAndAttributes _paa; foreach(PropertyInfo Property in type.GetProperties()) { //Create a new instance each time. _paa = new PropertyAndAttributes(); //Adds the property and generates an internal collection of attributes for it too _paa.AddProperty(Property); bool MapPropertyAndAttribute = true; //This is a class we need to map to another table if (Property.PropertyType.Namespace == "System.Collections.Generic") { 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; } } } //Add this to the list. if (MapPropertyAndAttribute) PAA.AddPaa(_paa); } return PAA; }
So given
GenericRepository<T>
, and I want to make aGenericRepository<string type obtained via reflection from the Property>
how would I do this? The line I need to replace with something that WORKS is://var x = Activator.CreateInstance("GenericRepository", Property.GetType().ToString());
Thanks.
-
Sergey Kalinichenko over 12 yearsHow is the property (the one of type
System.Collections.Generic
) declared in your C# code? Is its type argument<T>
the same as that of theGenericRepository<T>
that owns the property? -
Jordan over 12 yearsNo, basically it is just a generic collection of another class as a property on a class. i.e. A Teacher class has a list of classes class. The repository gets the teacher class and has to also process the classes class, but since it is really getting T it has to figure out what it has to process using reflection
-
Sergey Kalinichenko over 12 yearsSo is the property in the
Teacher
class declared asList<Class> Classes {/*getter and/or setter*/}
? Wouldn'tActivator.CreateInstance(Property.GetType())
work then? -
Jordan over 12 yearsah but I need a REPOSITORY [my own generic] of type T where T = Classes if the currently instanced repository is T = Teachers. What you suggest would work but just to create the type Classes
-
Sergey Kalinichenko over 12 yearsBoth answers below are correct then. Did they work for you?
-
Jordan over 12 yearsYes tested and both work. I +1 both but gave the best answer to the one that was easier to understand. Thank you both.
-
-
Jordan over 12 yearsIf I may, I am running into 1 problem. I cannot access any methods for the given repository. If I access it via the immediate window where it made say GenericRepository<Locations> and I do ?((GenericRepository<DocerZocer.Models.Location>)repository).GetAll() This properly works, how can I cast it properly in the code such that I don't need this? Obviously I can only do it in the immediate window because I know the type it represents.
-
Thomas Levesque over 12 years@Jordan, you could create a non-generic
IRepository
interface with aGetAll
method that returns an array of objects, and implement this interface explicitly in theGenericRepository<T>
class. Or you could call the method dynamically using reflection, but it's slower... -
Thomas Levesque over 12 yearsThis will create an instance of
GenericRepository<RuntimePropertyInfo>
, sinceProperty.GetType()
returnsRuntimePropertyInfo
...