How to create List<T> instance in C# file using Reflection
HI, I have a requirement to create instance for list object at runtime using reflection. For example I have 2 classes like below,
class Class1
{
List<Class2> class2List;
public List<Class2> Class2List
{
get;set;
}
}
class Class2
{
public string mem1;
public string mem2;
}
After creating the instance of Class1
at Runtime in another class Class3
, I want to assign values to all the properties of the class. In this case, Class2List
is a property of List<Class2>
. At Runtime, I don't know the class type of List<Class2>
. How can I ini开发者_如何学Pythontialize the property i.e. List<Class2>
inside class3 at runtime.
Any suggestions are greatly appreciated...
Rather than question your motives or try to unpick what you're doing - I'm just going to answer the question in the title.
Given you have a type instance listElemType
that represents the type argument that is to be passed to the List<>
type at runtime:
var listInstance = (IList)typeof(List<>)
.MakeGenericType(listElemType)
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
And then you can work with the list through it's IList
interface implementation.
Or, indeed, you can stop at the MakeGenericType
call and use the type it generates in a call to Activator.CreateInstance
- as in Daniel Hilgarth's answer.
Then, given a target
object whose property you want to set:
object target; //the object whose property you want to set
target.GetType()
.GetProperty("name_of_property") //- Assuming property is public
.SetValue(target, listInstance, null); //- Assuming .CanWrite == true
// on PropertyInfo
If you don't know the properties of the type represented by target
, then you need to use
target.GetType().GetProperties();
to get all the public properties of that instance. However just being able to create a list instance isn't really going to be able to help you there - you'll have to have a more generic solution that can cope with any type. Unless you're going to be specifically targetting list types.
Sounds to me like you might need a common interface or base...
Why do you need to use reflection to set the property?
After you created the instance of Class1
you can simply set the property:
Class1 instance = Activator.CreateInstanc<Class1>();
instance.Class2List = new List<Class2>();
Here a sample (without proper error handling!) that initializes the List property of Class1. What do you want to fill/initialize in a property/field of your object if you have an interface? What do you want to fill for other object types (maybe with more than 1 constructor parameter)?
Maybe an inversion of control container would serve you in your solution (like for example Ninject http://ninject.org/, Spring.Net http://www.springframework.net/, Unity http://unity.codeplex.com/) or the members are already correctly initialized in the objects you are using.
using System;
using System.Collections.Generic;
namespace ConsoleApplication3
{
public sealed class Class1
{
//[1]better solution (this way you wouldn't require reflection at all)
// private readonly List<Class2> _class2List = new List<Class2>();
private List<Class2> _class2List;
public List<Class2> Class2List
{
get { return _class2List; }
set {
_class2List = value; //set not allowed if you apply [1]
}
}
public string TestPropertyToIgnore { get; set; }
}
public class Class2
{
public string Mem1;
public string Mem2;
}
class Program
{
static void Main()
{
var typeClass1 = Type.GetType("ConsoleApplication3.Class1");
var objectClass1 = Activator.CreateInstance(typeClass1);
foreach(var property in objectClass1.GetType().GetProperties())
{
var propertyType = property.PropertyType;
if (!propertyType.IsClass
|| !property.CanRead
|| !property.CanWrite
|| property.GetValue(objectClass1, null) != null
|| !IsGenericListOfT(propertyType)
)
{
continue;
}
property.SetValue(objectClass1, Activator.CreateInstance(propertyType), null);
}
//this would raise a NullReference exception if list is still null
Console.WriteLine(((Class1) objectClass1).Class2List.Count);
}
private static bool IsGenericListOfT(Type propertyType)
{
return propertyType.IsGenericType
&& propertyType.GetGenericTypeDefinition() == typeof (List<>);
}
}
}
精彩评论