如何使用expression式设置属性值?

给定以下方法:

public static void SetPropertyValue(object target, string propName, object value) { var propInfo = target.GetType().GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); if (propInfo == null) throw new ArgumentOutOfRangeException("propName", "Property not found on target"); else propInfo.SetValue(target, value, null); } 

你将如何去写它的expression式启用的等价物,而不需要传入额外的目标参数?

为什么不直接设置属性,我可以听到你说。 例如,假设我们有一个拥有公共getter但私有setter的属性的类:

 public class Customer { public string Title {get; private set;} public string Name {get; set;} } 

我想能够打电话给:

 var myCustomerInstance = new Customer(); SetPropertyValue<Customer>(cust => myCustomerInstance.Title, "Mr"); 

现在这里是一些示例代码。

 public static void SetPropertyValue<T>(Expression<Func<T, Object>> memberLamda , object value) { MemberExpression memberSelectorExpression; var selectorExpression = memberLamda.Body; var castExpression = selectorExpression as UnaryExpression; if (castExpression != null) memberSelectorExpression = castExpression.Operand as MemberExpression; else memberSelectorExpression = memberLamda.Body as MemberExpression; // How do I get the value of myCustomerInstance so that I can invoke SetValue passing it in as a param? Is it possible } 

任何指针?

你可以用一个扩展方法作弊和使生活更轻松:

 public static class LambdaExtensions { public static void SetPropertyValue<T, TValue>(this T target, Expression<Func<T, TValue>> memberLamda, TValue value) { var memberSelectorExpression = memberLamda.Body as MemberExpression; if (memberSelectorExpression != null) { var property = memberSelectorExpression.Member as PropertyInfo; if (property != null) { property.SetValue(target, value, null); } } } } 

接着:

 var myCustomerInstance = new Customer(); myCustomerInstance.SetPropertyValue(c => c.Title, "Mr"); 

之所以这更容易,是因为你已经拥有了调用扩展方法的目标。 此外,lambdaexpression式是一个简单的成员expression式,没有闭包。 在你最初的例子中,目标是在一个闭包中捕获的,到底层目标和PropertyInfo可能有点棘手。