如何基于字段字符串列表构建Employee类的表达式树列表?
动态生成Employee属性表达式列表
问题背景
现有如下C# Employee类定义:
class Employee { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } }
需要根据字符串字段列表 var fields = new List<string>() { "Id", "Name" };,动态生成List<Expression<Func<Employee, object>>>类型的表达式列表,效果等价于手动编写:
var expressions = new List<Expression<Func<Employee, object>>>() { e => e.Id, e => e.Name };
实现方案
通过反射获取Employee类的属性信息,结合表达式树动态构建Lambda表达式,具体步骤如下:
- 定义Employee类型的参数表达式;
- 遍历目标字段列表,对每个字段名:
- 查找对应的PropertyInfo;
- 构建成员访问表达式(访问该属性);
- 若属性是值类型,需添加装箱转换(转为object);
- 最终构建完整的Lambda表达式并加入列表。
完整代码示例
using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; class Employee { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } } class Program { static void Main() { var fields = new List<string>() { "Id", "Name" }; var expressions = BuildExpressions(fields); // 验证输出(可选) foreach (var expr in expressions) { Console.WriteLine(expr.ToString()); } } static List<Expression<Func<Employee, object>>> BuildExpressions(List<string> fieldNames) { var employeeType = typeof(Employee); var parameterExpr = Expression.Parameter(employeeType, "e"); var expressions = new List<Expression<Func<Employee, object>>>(); foreach (var fieldName in fieldNames) { // 获取对应属性信息 var propertyInfo = employeeType.GetProperty(fieldName, BindingFlags.Public | BindingFlags.Instance); if (propertyInfo == null) continue; // 字段不存在时跳过,可根据需求添加异常处理 // 构建成员访问表达式:e => e.PropertyName var memberExpr = Expression.Property(parameterExpr, propertyInfo); // 处理值类型装箱:将值类型转为object Expression convertExpr = memberExpr; if (propertyInfo.PropertyType.IsValueType) { convertExpr = Expression.Convert(memberExpr, typeof(object)); } // 构建Lambda表达式并添加到列表 var lambdaExpr = Expression.Lambda<Func<Employee, object>>(convertExpr, parameterExpr); expressions.Add(lambdaExpr); } return expressions; } }
代码说明
- 反射获取属性:使用
Type.GetProperty方法查找Employee类中匹配的公共实例属性; - 表达式树构建:通过
Expression.Parameter定义参数e,Expression.Property创建属性访问节点; - 值类型装箱:因为返回类型是
object,值类型(如int)需要通过Expression.Convert完成装箱转换,避免类型不匹配; - 异常处理:代码中对不存在的字段做了跳过处理,可根据业务需求改为抛出异常。
内容的提问来源于stack exchange,提问作者Mayank Gupta
相关产品推荐
相关产品推荐

