代码之家  ›  专栏  ›  技术社区  ›  John Sheehan

通过反射将项目动态添加到List<T>

  •  17
  • John Sheehan  · 技术社区  · 16 年前

    假设我有这门课

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

    我正在开发一个反序列化器,我希望能够创建和填充 Child

    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 回复  |  直到 7 年前
        1
  •  21
  •   bobbymcr    16 年前

    System.Collections.IList 并直接调用Add方法。优点:简单,没有丑陋的反射。缺点:导致包含值类型的列表装箱。

        2
  •  19
  •   ChaosPandion    16 年前

    这应该行得通,除非我真的错过了什么。

    循环之外

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

    循环内部

    add.Invoke(list, new[] { item });
    
        3
  •  1
  •   Scott Dorman    16 年前

    你需要打电话 type.MakeGenericType(type.GetGenericArguments()) ,它将返回正确的封闭泛型类型。然后,您需要反思性地致电 Add

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

    instance ,但这是将调用该方法的实际对象。

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

        4
  •  0
  •   Alen.Toma    9 年前

    这就是我的工作

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