让我说我有这个班级
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方法并添加项目。
答案 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)