【问题标题】:Dynamically adding items to a List<T> through reflection通过反射将项目动态添加到 List<T>
【发布时间】:2009-10-10 03:00:43
【问题描述】:

假设我有这门课

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&lt;t.GetType()&gt;,因此我可以访问 add 方法并添加项目。

【问题讨论】:

    标签: c# generics reflection


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      这应该可以工作,除非我真的错过了什么。

      循环之外

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

      循环内部

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

      【讨论】:

      • 这是一个很好的答案,非常感谢您的回复,所以 +1。 bobbymcr 的作品虽然不使用反射,所以我会这样做。再次感谢。
      【解决方案3】:

      您需要调用type.MakeGenericType(type.GetGenericArguments()),它将返回正确的封闭泛型类型。然后,您需要反思地调用 Add 方法。代码应如下所示:

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

      我不确定你会使用什么作为instance,但这是调用方法的实际对象。

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

      【讨论】:

      • 我知道有人会问“为什么?” XmlSerializer 有一些限制(不支持 List 最显着),我探索的其他选项对于这个项目来说太冗长了(这将是一个框架,所以如果它在一个较低的级别运行,它很好我)。基本上为了实现我正在寻找的简单性,我必须自己动手。
      • @John Sheehan:为什么生成的序列化数据对您来说很有趣/很重要?除了 XmlSerializer 之外,还有其他可用的序列化程序,例如 WCF 数据协定序列化程序。它可以轻松使用并支持List&lt;T&gt;。是的,它可以生成一些难看的 XML,但一般来说这不重要。
      • 我不需要序列化,只需要反序列化,我不想使用任何属性。
      【解决方案4】:

      这就是我的工作

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多