开发者

Dynamically adding items to a List<T> through reflection

开发者 https://www.devze.com 2022-12-08 00:25 出处:网络
Lets say I have this class class Child { public string FirstName { get; set; } public string LastName { get; set; }

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)
0

精彩评论

暂无评论...
验证码 换一张
取 消