本文介绍对列表进行创建及赋值的反射操作

我们现在有TestA、TestB类,TestA中有TestB类型列表的属性List,如下:

1     public class TestA
2 {
3 public List<TestB> List { get; set; }
4 }
5 public class TestB
6 {
7 public TestB(string name)
8 {
9 Name = name;
10 }
11 public string Name { get; }
12

下面通过反射,给TestA.List进行赋值,output的期望是 “1,2”

1     var testA = new TestA();
2 var list = new List<TestB>() { new TestB("1"), new TestB("2") };
3 AddValueToListProperty(testA, nameof(TestA.List), list);
4 var output = string.Join(",", testA.List.Select(i => i.Name));

1. 确定列表及泛型时,可以直接设置属性值

1     private void AddValueToListProperty(object objectValue, string propertyName, List<TestB> list)
2 {
3 var propertyInfo = objectValue.GetType().GetProperty(propertyName);
4 propertyInfo.SetValue(objectValue, list, null);
5

2.确定属性是列表,但不确定列表的泛型时,通过列表的Add方式进行设置值

List<object> list按上方的方案1,是无法进行赋值的,因为类型不一样。会提示隐示转换异常。

1     private void AddValueToListProperty(object objectValue, string propertyName, List<object> list)
2 {
3 var propertyInfo = objectValue.GetType().GetProperty(propertyName);
4 var newList = Activator.CreateInstance(typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GenericTypeArguments));
5 propertyInfo.SetValue(objectValue, newList, null);
6 var addMethod = newList.GetType().GetMethod("Add");
7 foreach (var item in list)
8 {
9 addMethod.Invoke(newList, new object[] { item });
10 }
11

如上,我们需要先创建一个空列表,对属性进行初始化。propertyInfo.PropertyType.GenericTypeArguments是列表的泛型类型

然后,获取列表的新增方法 newList.GetType().GetMethod("Add"),将List<object> list一项项添加到列表中。

3.不确定属性是否列表,也不确定列表的泛型,可以如下处理:

1     private void AddValueToListProperty(object objectValue, string propertyName, object list)
2 {
3 var propertyInfo = objectValue.GetType().GetProperty(propertyName);
4 if (typeof(System.Collections.IList).IsAssignableFrom(propertyInfo.PropertyType))
5 {
6 var newList = Activator.CreateInstance(typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GenericTypeArguments));
7 propertyInfo.SetValue(objectValue, newList, null);
8 var addMethod = newList.GetType().GetMethod("Add");
9 foreach (var item in (IEnumerable)list)
10 {
11 addMethod.Invoke(newList, new object[] { item });
12 }
13 }
14 else
15 {
16 propertyInfo.SetValue(objectValue, list, null);
17 }
18

如果AddValueToListProperty方法是设置属性值的通用方法,一般可以按上面的方式进行处理。

当然上面的一些代码是简化后的处理,比如判断是否列表,还需要更严谨的判断见《​​C# 反射 判断类型是否是列表​​》

作者:​​唐宋元明清2188​