如何使用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
可能有点棘手。