如何使用表达式设置属性值?

给出以下方法:

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);
}

如何在不需要为 target 传入额外参数的情况下编写它的启用表达式等价物?

为什么要这样做,而不是直接设置属性,我可以听到你说。例如,假设我们有以下类,其属性具有一个公共 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


}

有什么建议吗?

52424 次浏览

You could cheat and make life easier with an extension method:

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);
}
}
}
}

and then:

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

The reason why this is easier is because you already have the target on which the extension method is invoked. Also the lambda expression is a simple member expression without closures. In your original example the target is captured in a closure and it could be a bit tricky to get to the underlying target and PropertyInfo.