如何通过C#表达式树为Person类的Contacts集合属性赋值?
问题分析与解决方案
哦,我一眼就看到你出错的地方了——你找错了Add方法的所属类型!你的Person.Contacts是List<Contact>类型,但你却去获取List<Person>的Add方法,类型完全不匹配,这肯定会触发异常。
下面给你两种正确的实现方式,用表达式树把那些MemberInitExpression形式的Contact实例填充到Person的Contacts属性里:
方式一:用ListInit直接初始化集合(更简洁)
这种方式利用表达式树的ListInit特性,直接创建List<Contact>并批量添加元素,代码更紧凑:
// 假设你的MemberInitExpression集合是:IEnumerable<MemberInitExpression> contactInits var listAddMethod = typeof(List<Contact>).GetMethod("Add", new[] { typeof(Contact) }); // 1. 创建List<Contact>的初始化表达式,批量添加所有Contact实例 var contactsListInit = Expression.ListInit( Expression.New(typeof(List<Contact>)), contactInits.Select(contactInit => Expression.ElementInit(listAddMethod, contactInit) ) ); // 2. 创建Person实例并赋值Contacts属性 var personInitExpr = Expression.MemberInit( Expression.New(typeof(Person)), Expression.Bind( typeof(Person).GetProperty(nameof(Person.Contacts)), contactsListInit ) ); // 3. 编译成委托并执行 var createPerson = Expression.Lambda<Func<Person>>(personInitExpr).Compile(); Person resultPerson = createPerson();
方式二:用Block表达式分步操作(更直观)
如果你想更清晰地看到每一步的逻辑,可以用Block表达式分步创建列表、添加元素、赋值给Person:
// 假设你的MemberInitExpression集合是:IEnumerable<MemberInitExpression> contactInits var listAddMethod = typeof(List<Contact>).GetMethod("Add", new[] { typeof(Contact) }); // 1. 定义一个变量来存储Contacts列表 var listVar = Expression.Variable(typeof(List<Contact>), "contactsList"); // 2. 创建列表实例并赋值给变量 var assignList = Expression.Assign(listVar, Expression.New(typeof(List<Contact>))); // 3. 生成所有Add元素的表达式 var addContactExprs = contactInits.Select(contactInit => Expression.Call(listVar, listAddMethod, contactInit) ); // 4. 创建Person实例并将列表赋值给Contacts属性 var personExpr = Expression.MemberInit( Expression.New(typeof(Person)), Expression.Bind(typeof(Person).GetProperty(nameof(Person.Contacts)), listVar) ); // 5. 组合所有步骤成Block表达式 var blockExpr = Expression.Block( new[] { listVar }, assignList, Expression.AddRange(addContactExprs), personExpr ); // 6. 编译执行 var createPerson = Expression.Lambda<Func<Person>>(blockExpr).Compile(); Person resultPerson = createPerson();
关键修正点
你之前的代码错误在于:
// 错误:拿了List<Person>的Add方法,和Contacts的List<Contact>类型不匹配 var method = typeof(List<Person>).GetMethods().Where(m => m.Name == "Add").First().MakeGenericMethod(typeof(Person));
正确的做法是获取List<Contact>的Add方法,而且不需要调用MakeGenericMethod——因为List<Contact>已经是具体的泛型类型,它的Add方法参数就是Contact,直接获取即可。
内容的提问来源于stack exchange,提问作者user7784348
相关产品推荐
相关产品推荐

