如何从Func<T>委托中获取目标属性/字段的名称?
解决从Func委托中获取目标字段/属性名称的问题
你遇到的核心问题是:直接使用Func<T>委托时,lambda表达式会被编译成匿名方法(比如<InitialiseModel>b__7_0),丢失了原始的成员访问结构信息,所以无法直接提取目标字段名。要解决这个问题,需要改用表达式树Expression<Func<T>>来替代Func<T>,因为表达式树会保留lambda的语法结构,允许我们解析出目标成员的名称。
步骤1:修改PointerVariable<T>类,支持表达式树
将AddGetter方法的参数从Func<T>改为Expression<Func<T>>,同时添加解析成员名称的逻辑:
public class PointerVariable<T> { private Func<T> _getter; public string TargetMemberName { get; private set; } public void AddGetter(Expression<Func<T>> getterExpression) { // 编译表达式为委托,保留原有的调用能力 _getter = getterExpression.Compile(); // 解析表达式,提取目标成员名称 if (getterExpression.Body is MemberExpression memberExpr) { TargetMemberName = memberExpr.Member.Name; } // 处理值类型装箱转换的情况 else if (getterExpression.Body is UnaryExpression unaryExpr && unaryExpr.Operand is MemberExpression operandMember) { TargetMemberName = operandMember.Member.Name; } else { throw new ArgumentException("传入的表达式必须是直接访问字段或属性的lambda"); } } // 保留获取值的方法(可选) public T GetValue() { return _getter(); } }
步骤2:修改调用代码
调用AddGetter时,传入的lambda会自动被编译器转换为Expression<Func<T>>,无需额外改动:
public class Model : MonoBehaviour { protected PointerVariable<bool> _isEnabledVar; public virtual void InitialiseModel() { _isEnabledVar.AddGetter(() => enabled); // 直接获取目标字段名"enabled" string fieldName = _isEnabledVar.TargetMemberName; } }
为什么Func<T>不行?
Func<T>是编译后的委托实例,仅包含指向IL代码的引用,没有保留lambda表达式的原始结构(比如“访问哪个字段”)。而Expression<Func<T>>是表达式树,它是对lambda语法结构的抽象描述,我们可以通过遍历表达式树节点,提取出成员访问的具体信息。
注意事项
- 该方法仅适用于lambda直接访问字段/属性的场景(如
() => enabled),如果lambda包含复杂逻辑(如() => enabled && IsReady),解析会失败,需根据实际场景扩展解析逻辑。 - 只要lambda所在上下文有权访问目标成员,表达式树就能正常解析,无论成员是protected还是private。
内容的提问来源于stack exchange,提问作者Jake Slack
相关产品推荐
相关产品推荐

