如何获取委托中对象初始化时赋值属性的源属性名称?
获取对象初始化表达式中的属性映射源名称
要获取Foo所赋值的源属性名称(比如示例中的ObjA.Bar),必须使用表达式树——因为普通的Func<ObjA, ObjB>委托编译后会丢失元数据结构,只有表达式树能保留初始化逻辑的完整信息。
实现步骤
- 将原委托定义为
Expression<Func<ObjA, ObjB>>类型,而非直接的Func<ObjA, ObjB>,这样才能保留表达式结构。 - 解析表达式树的对象初始化节点,匹配目标属性(如
Foo)对应的赋值表达式。 - 提取赋值表达式中的源属性路径。
代码示例
首先定义实体类:
public class ObjA { public string Bar { get; set; } public int Bar1 { get; set; } } public class ObjB { public string Foo { get; set; } public int Foo1 { get; set; } }
定义表达式并编写解析方法:
// 定义带表达式树的映射逻辑 Expression<Func<ObjA, ObjB>> mapExpr = a => new ObjB { Foo = a.Bar, Foo1 = a.Bar1 }; // 解析目标属性对应的源属性名称 public static string GetSourceProperty(Expression<Func<ObjA, ObjB>> expr, string targetPropName) { if (expr.Body is not NewExpression initExpr) throw new ArgumentException("仅支持对象初始化表达式"); // 找到目标属性在初始化列表中的位置 var propIndex = initExpr.Members .Select(m => m.Name) .ToList() .IndexOf(targetPropName); if (propIndex == -1) throw new ArgumentException($"未找到目标属性:{targetPropName}"); // 获取赋值的源表达式 var sourceExpr = initExpr.Arguments[propIndex]; // 解析单层属性(多层属性可扩展递归逻辑) if (sourceExpr is MemberExpression memberExpr) { var paramName = ((ParameterExpression)memberExpr.Expression).Name; var propName = memberExpr.Member.Name; return $"{paramName}.{propName}"; } throw new NotSupportedException("暂不支持复杂表达式赋值"); }
调用示例:
var sourceProp = GetSourceProperty(mapExpr, "Foo"); Console.WriteLine(sourceProp); // 输出:a.Bar
扩展说明
如果需要支持多层属性(如a.NestedObj.Bar),可以给解析方法添加递归逻辑,逐层遍历MemberExpression拼接完整路径:
private static string GetPropertyPath(Expression expr) { if (expr is MemberExpression memberExpr) { var parentPath = GetPropertyPath(memberExpr.Expression); return string.IsNullOrEmpty(parentPath) ? memberExpr.Member.Name : $"{parentPath}.{memberExpr.Member.Name}"; } if (expr is ParameterExpression paramExpr) { return paramExpr.Name; } throw new NotSupportedException("不支持的表达式类型"); }
修改GetSourceProperty方法中返回值为GetPropertyPath(sourceExpr)即可。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

