获取作为lambda表达式传递的参数的PropertyInfo

例如,我有一个class级:

public class Person { public int Id; public string Name, Address; } 

我想调用一个方法来更新此类中基于Id的信息

 update(myId, myPerson => myPerson.Name = "abc"); 

解释:此方法将从数据库中查询并获取给定myId的 Person实体,然后将Name设置为“abc”,因此它执行的工作与我调用的相同:

 update(myId, myPerson => myPerson.Address = "my address"); 

可能吗? 如果是这样的话?

这是可能的,并且不需要使用PropertyInfo

你可以这样设计你的方法:

 public bool Update(int id, Action updateMethod) // where T : SomeDbEntityType { T entity = LoadFromDatabase(id); // Load your "person" or whatever if (entity == null) return false; // If you want to support fails this way, etc... // Calls the method on the person updateMethod(entity); SaveEntity(entity); // Do whatever you need to persist the values return true; } 

我不会像Reed Copsey在他的回答中所说的那样使用PropertyInfo ,但仅仅是为了获取信息,您可以使用以下方法提取表达式的PropertyInfo

 public PropertyInfo GetPropertyFromExpression(Expression> GetPropertyLambda) { MemberExpression Exp = null; //this line is necessary, because sometimes the expression comes in as Convert(originalexpression) if (GetPropertyLambda.Body is UnaryExpression) { var UnExp = (UnaryExpression)GetPropertyLambda.Body; if (UnExp.Operand is MemberExpression) { Exp = (MemberExpression)UnExp.Operand; } else throw new ArgumentException(); } else if (GetPropertyLambda.Body is MemberExpression) { Exp = (MemberExpression)GetPropertyLambda.Body; } else { throw new ArgumentException(); } return (PropertyInfo)Exp.Member; } 

对于像MyPerson.PersonData.PersonID这样的复合表达式,您可以获取子表达式,直到它们不再是MemberExpressions

 public PropertyInfo GetPropertyFromExpression(Expression> GetPropertyLambda) { //same body of above method without the return line. //.... //.... //.... var Result = (PropertyInfo)Exp.Member; var Sub = Exp.Expression; while (Sub is MemberExpression) { Exp = (MemberExpression)Sub; Result = (PropertyInfo)Exp.Member; Sub = Exp.Expression; } return Result; //beware, this will return the last property in the expression. //when using GetValue and SetValue, the object needed will not be //the first object in the expression, but the one prior to the last. //To use those methods with the first object, you will need to keep //track of all properties in all member expressions above and do //some recursive Get/Set following the sequence of the expression. } 

这是@DanielMöller的一个版本,它更新了现代语法,包含指定的exception消息和文档。

 ///  /// Gets the corresponding  from an . ///  /// The expression that selects the property to get info on. /// The property info collected from the expression. /// When  is null. /// The expression doesn't indicate a valid property." private PropertyInfo GetPropertyInfo(Expression> property) { if (property == null) { throw new ArgumentNullException(nameof(property)); } if (property.Body is UnaryExpression unaryExp) { if (unaryExp.Operand is MemberExpression memberExp) { return (PropertyInfo)memberExp.Member; } } else if (property.Body is MemberExpression memberExp) { return (PropertyInfo)memberExp.Member; } throw new ArgumentException($"The expression doesn't indicate a valid property. [ {property} ]"); }