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

Ana*_*yal 59 c# linq 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);
}
Run Code Online (Sandbox Code Playgroud)

如何编写它的表达式启用等效而无需为目标传递额外的参数?

为什么这样做而不是直接设置属性我可以听到你说.例如,假设我们有以下类,其属性具有公共getter但私有setter:

public class Customer 
{
   public string Title {get; private set;}
   public string Name {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

我希望能够致电:

var myCustomerInstance = new Customer();
SetPropertyValue<Customer>(cust => myCustomerInstance.Title, "Mr");
Run Code Online (Sandbox Code Playgroud)

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

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

}
Run Code Online (Sandbox Code Playgroud)

有什么指针吗?

Dar*_*rov 121

您可以使用扩展方法作弊并使生活更轻松:

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

var myCustomerInstance = new Customer();
myCustomerInstance.SetPropertyValue(c => c.Title, "Mr");
Run Code Online (Sandbox Code Playgroud)

这更容易的原因是因为您已经拥有调用扩展方法的目标.lambda表达式也是一个没有闭包的简单成员表达式.在您的原始示例中,目标是在闭包中捕获的,并且到达底层目标可能有点棘手PropertyInfo.

  • Property.SetValue是反射.你不应该使用它. (16认同)
  • 这似乎不适用于嵌套对象,你知道我如何解决这个问题 (3认同)
  • 您可以使用泛型类型作为值类型:`public static void SetPropertyValue <T,TValue>(此T目标,Expression <Func <T,TValue >> memberLamda,TValue值){var memberSelectorExpression = memberLamda.Body as MemberExpression; if(memberSelectorExpression!= null){var property = memberSelectorExpression.Member as PropertyInfo; if(property!= null){property.SetValue(target,value,null); } (3认同)
  • @Mboros:使用反射有什么问题?也许它很慢,如果你进行数百万次操作,但偶尔...... (3认同)
  • 我已将 @pinus.acer 的评论合并到答案中,因为它对我有用。 (2认同)