C# instantiate generic List from reflected Type
Try this:
void foobar(Type t)
{
var listType = typeof(List<>);
var constructedListType = listType.MakeGenericType(t);
var instance = Activator.CreateInstance(constructedListType);
}
Now what to do with instance
? Since you don't know the type of your list's contents, probably the best thing you could do would be to cast instance
as an IList
so that you could have something other than just an object
:
// Now you have a list - it isn't strongly typed but at least you
// can work with it and use it to some degree.
var instance = (IList)Activator.CreateInstance(constructedListType);
Create generic ListT with reflection
Assuming you know the property name, and you know it is an IEnumerable<T>
then this function will set it to a list of corresponding type:
public void AssignListProperty(Object obj, String propName)
{
var prop = obj.GetType().GetProperty(propName);
var listType = typeof(List<>);
var genericArgs = prop.PropertyType.GetGenericArguments();
var concreteType = listType.MakeGenericType(genericArgs);
var newList = Activator.CreateInstance(concreteType);
prop.SetValue(obj, newList);
}
Please note this method does no type checking, or error handling. I leave that as an exercise to the user.
Using Reflection.Emit to instantiate Generic Type with Generic Parameters
Yeah, there's definitely a trick to this. Indeed you cannot call any methods on the TypeBuilderInstantiation
. Instead, TypeBuilder
will let you get constructors for dependent types.
The
GetConstructor
method provides a way to get aConstructorInfo
object that represents a constructor of a constructed generic type whose generic type definition is represented by aTypeBuilder
object.
https://msdn.microsoft.com/en-us/library/ms145822(v=vs.110).aspx
You first need the generic ConstructorInfo
, gotten from typeof(List<>)
in the usual way...
var listDefaultConstructor = listType.GetConstructor(new Type[0]);
and then instantiate it to your particular generic implementation:
var c = TypeBuilder.GetConstructor(list_of_T, listDefaultConstructor);
Whenever you would like to call a method on an instance of Type
that represents an unconstructed/dependent type, instead look for a method with the same name in the Reflection.Emit hierarchy.
Among other things, this design pattern of passing in the generic version of the MethodInfo
allows you to distinguish between calls to overloaded Class<T=int>.Foo(T)
and Class<T=int>.Foo(int)
.
passing generic list of reflected type to method in reflected type
What I tried so far:
- Passing a List containing stStruct items.
Without code thats hard to say what was wrong.
- Creating a struct that has the same definition as stStruct (cstStruct) in my code, then passing a List to the processItems method. (cannot convert list of x to list of y).
Well thats how typesafe languages work, its a different type.
The key to solve this problem is the Type.MakeGenericType
method to create a generic type with a type parameter unknown at compile time. Keep in mind that the Assembly.GetType()
method requires the type name inclusive the namespace. You can inline a few of these temp variables, i created them just to be a bit more clear about the general reflection process.
var businessTypeInstance = ...;
var processItemsMethod = businessTypeInstance.GetType().GetMethod("processItems");
var stStructType = businessTypeInstance.GetType().Assembly.GetType("stStruct");
var openListType = typeof(List<>);
var closedListType = openListType.MakeGenericType(stStructType);
var listOfStruct = Activator.CreateInstance(closedListType);
var result = processItemsMethod.Invoke(businessTypeInstance, new [] { listOfStruct });
Just for broaden the mind and even that i do not recommend this, you could get the
List<stStruct>
type from the parameter itself:var closedListType = processItemsMethod.GetParameters()[0].ParameterType;
how to create a list of type obtained from reflection
var listType = typeof(List<>).MakeGenericType(myType)
var list = Activator.CreateInstance(listType);
var addMethod = listType.GetMethod("Add");
addMethod.Invoke(list, new object[] { x });
You might be able to cast to IList
and call Add
directly instead of looking up the method with reflection:
var list = (IList)Activator.CreateInstance(listType);
list.Add(x);
Generic list by using reflection
Closest you can get:
Type listType = typeof(List<>).MakeGenericType(_type);
IList list = (IList) Activator.CreateInstance(listType);
Instantiate generic c# List when the reflected type itself is a List
Have a look at this example, it uses the Type.GetGenericArguments Method to retrieve the lists inner type. Then proceed with reflection as usual.
static void Main(string[] args)
{
Type modelType = GetMyType();
var myList = Activator.CreateInstance(modelType);
var listInnerType = modelType.GetGenericArguments()[0];
var listInnerTypeObject = Activator.CreateInstance(listInnerType);
var addMethod = modelType.GetMethod("Add");
addMethod.Invoke(myList, new[] { listInnerTypeObject });
}
static Type GetMyType()
{
return typeof(List<>).MakeGenericType((new Random().Next(2) == 0) ? typeof(A) : typeof(B));
}
class A { }
class B { }
Add instance of Generic List to object using reflection
Im running the code from your question with some minor changes to make it compile and it seems to work fine:
void Main()
{
Parse<Foo>();
}
public static T Parse<T>() where T : new()
{
var returnObj = new T();
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo p in properties)
{
// Get a meaningful property name
string ins = p.PropertyType.Name;
switch(ins)
{
// populate int
case "Int32":
p.SetValue(returnObj, 1 , null);
break;
// populate list
case "IList`1":
var list = new List<string>();
// This will throw the exception 'Parameter count mismatch.'
p.SetValue(returnObj, list, null);
break;
}
}
return returnObj;
}
public class Foo
{
public virtual int someInt {get; set;}
public virtual IList<string> list {get; set;}
}
If you change the Foo
to have an indexer property that returns IList
on the other hand you get the exception in your question:
public class Foo
{
public virtual int someInt {get; set;}
public virtual IList<string> this[int key]
{
get{ return null; }
set
{
}
}
}
Generates:
TargetParameterCountException: Parameter count mismatch.
instantiate a generic class using reflection
Regarding your update, you can pass any Type
to MakeGenericType
. For example, the following also works:
var myObject = new MyClass();
var myGenericObject = Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(typeof(MyClass)), myObject);
Console.WriteLine(myGenericObject.GetType());
Outputs:
ConsoleApplication1.GenericClass`1[ConsoleApplication1.MyClass]
myObject.GetType()
also does the same thing:
var myGenericObject = Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(myObject.GetType()), myObject);
Related Topics
How to Turn Off Impersonation Just in a Couple Instances
Newtonsoft JSON.Net Serialize Jobject Doesn't Ignore Nulls, Even with the Right Settings
C# Creating an Unknown Generic Type at Runtime
Get User Location by Ip Address
Datetimepicker: Pick Both Date and Time
How to Export Datagridview Data Instantly to Excel on Button Click
Start May Not Be Called on a Promise-Style Task. Exception Is Coming
How to Retrieve Disk Information in C#
How to Confirm That Mail Has Been Delivered or Not
How to Show the "Open With" File Dialog
How to Quickly Up-Cast Object[,] into Double[,]
C#: HTMLagilitypack Extract Inner Text
What Are the Differences Between Various Threading Synchronization Options in C#
Difference Between System.Datetime.Now and System.Datetime.Today