2009-10-10 52 views
14

将项目添加到列表 可以说我有这个类 动态通过反射

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方法并添加项目。

回答

19

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

+0

我喜欢这个主意。 – 2009-10-10 03:08:27

17

这应该工作,除非我真的失去了一些东西。

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

的外循环

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

这是一个很好的答案,我很欣赏你的回复,所以+1。虽然bobbymcr的作品并没有使用反射,所以我正在与此。再次感谢。 – 2009-10-10 03:13:23

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已经包含知道如何完成所有这类工作的序列化程序。如果可以的话,你应该使用其中的一种,而不是试图“推出自己的”。

+0

我知道有人会问“为什么?” XmlSerializer有一些限制(最显着的是不支持List ),我研究的其他选项对于这个项目来说太冗长了(这将成为一个框架,所以如果它在一个较低的层次上运行,对我来说就没问题) 。基本上为了达到简单我正在寻找,我必须推出自己的。 – 2009-10-10 03:15:23

+0

@John Sheehan:为什么产生的序列化数据对您来说很重要?除了XmlSerializer之外,还有其他序列化器可用,例如WCF数据协定序列化器。它可以很容易地使用并支持'List '。是的,它可能会产生一些看起来丑陋的XML,但一般来说这应该不重要。 – 2009-10-10 04:14:02

+0

我不需要序列化,只需要反序列化,我不想使用任何属性。 – 2009-10-10 20:04:04

0

这是我做的

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