Dynamically adding items to a List<T> through reflection
Lets say I have this class
class Child {
public string FirstName { get; set; }
public string LastName { get; set; }
}
class Container {
public List<Child> { get; set; }
}
I'm working on a deserializer of sorts and I want to be able to create and populate the Child
list from the data retrie开发者_JS百科ved. I've gotten this far (I've cut out a lot of handling for other types for this example so its unnecessarily "iffy" but bear with me):
var props = typeof(Container).GetProperties();
foreach (var prop in props) {
var type = prop.PropertyType;
var name = prop.Name;
if (type.IsGenericType) {
var t = type.GetGenericArguments()[0];
if (type == typeof(List<>)) {
var list = Activator.CreateInstance(type);
var elements = GetElements();
foreach (var element in elements) {
var item = Activator.CreateInstance(t);
Map(item, element);
// ??? how do I do list.Add(item) here?
}
prop.SetValue(x, list, null); // x is an instance of Container
}
}
}
I can't figure out how to cast list
to essentially List<t.GetType()>
so I can access the add method and add the item.
I would say you should cast down to System.Collections.IList
and directly call the Add method. Pros: simple, no ugly reflection. Cons: causes boxing for Lists containing value types.
This should work unless I am really missing something.
Outside of the loop
var add = type.GetMethod("Add");
Inside the loop
add.Invoke(list, new[] { item });
You need to call type.MakeGenericType(type.GetGenericArguments())
, which will return the correct closed generic type. You would then need to reflectively call the Add
method. The code should look something like this:
Type listType = type.MakeGenericType(type.GetGenericArguments());
MethodInfo addMethod = listType.GetMethod("Add");
addMethod.Invoke(instance, new object[] { ... });
I'm not sure what you would use as instance
, but this is the actual object on which the method will be invoked.
The better question to ask is why are you trying to do this? The .NET Framework already includes serializers that know how to do all of this type of work. If you can, you should be using one of those instead of trying to "roll your own".
this is what i do
var genericType = _primaryType.GetGenericArguments().First();
var type = typeof(List<>).MakeGenericType(genericType);
IList o = (IList)Activator.CreateInstance(type);
o.Add(x)
精彩评论