【问题标题】:How to set property value using Expressions? [duplicate]如何使用表达式设置属性值? [复制]
【发布时间】:2012-03-24 23:51:54
【问题描述】:

给定以下方法:

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

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

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

}

有什么建议吗?

【问题讨论】:

标签: c# linq expression


【解决方案1】:

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

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

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

【讨论】:

  • Property.SetValue 是反射。你不应该使用它。
  • 这似乎不适用于嵌套对象,你知道我是如何解决这个问题的
  • 值类型可以使用泛型:public static void SetPropertyValue&lt;T, TValue&gt;(this T target, Expression&lt;Func&lt;T, TValue&gt;&gt; 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); } } }
  • 我已将 @pinus.acer 的评论纳入答案,因为它对我有用。
  • @Mboros:使用反射有什么问题?如果您进行数百万次操作,可能会很慢,但偶尔...
猜你喜欢
  • 1970-01-01
  • 2019-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-14
  • 1970-01-01
相关资源
最近更新 更多