通过反射</t>动态地将项目添加到List <t>

时间:2009-10-10 03:00:43

标签: c# generics reflection

让我说我有这个班级

class Child {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Container {
    public List<Child> { get; set; }
}

我正在研究各种各样的反序列化器,我希望能够从检索到的数据中创建和填充Child列表。我已经做到了这一点(我已经为这个例子减少了很多其他类型的处理,所以它不必要地“iffy”但是请耐心等待我:)

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

        }
    }
}

我无法弄清楚如何将list转换为List<t.GetType()>,因此我可以访问add方法并添加项目。

4 个答案:

答案 0 :(得分:21)

我会说你应该转向System.Collections.IList并直接调用Add方法。优点:简单,没有丑陋的反思。缺点:导致包含值类型的列表装箱。

答案 1 :(得分:19)

这应该有效,除非我真的错过了什么。

在循环之外

var add = type.GetMethod("Add");

循环内

add.Invoke(list, new[] { item });

答案 2 :(得分:1)

您需要调用type.MakeGenericType(type.GetGenericArguments()),它将返回正确的封闭泛型类型。然后,您需要反射性地调用Add方法。代码看起来像这样:

   Type listType = type.MakeGenericType(type.GetGenericArguments());
   MethodInfo addMethod = listType.GetMethod("Add");
   addMethod.Invoke(instance, new object[] { ... });

我不确定您将使用instance,但这是调用该方法的实际对象。

更好的问题是你为什么要这样做? .NET Framework已经包含了解如何完成所有此类工作的序列化程序。如果可以的话,你应该使用其中一种,而不是试图“自己动手”。

答案 3 :(得分:0)

这就是我做的事情

    var genericType = _primaryType.GetGenericArguments().First();
    var type = typeof(List<>).MakeGenericType(genericType);
    IList o = (IList)Activator.CreateInstance(type);
    o.Add(x)