如何使用表达式设置属性值? [英] How to set property value using Expressions?

查看:140
本文介绍了如何使用表达式设置属性值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下方法:

  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,在目标上找不到属性);
else
propInfo.SetValue(target,value,null);
}

你如何去写它的表达式启用相当于不需要传入额外的目标参数?



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

  public class Customer 
{
public string Title {get; private set;}
public string Name {get;我想要能够调用:

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

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

  public static void SetPropertyValue< T>(表达式< Func< T,Object>> memberLamda,对象值)
{
MemberExpression memberSelectorExpression;
var selectorExpression = memberLamda.Body;
var castExpression = selectorExpression为UnaryExpression;

if(castExpression!= null)
memberSelectorExpression = castExpression.Operand作为MemberExpression;
else
memberSelectorExpression = memberLamda.Body as MemberExpression;

//如何获取myCustomerInstance的值,以便我可以调用SetValue作为参数传递它?是否可能

}

任何指针?

解决方案

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

  public static class LambdaExtensions 
{
public static void SetPropertyValue< T,TValue>(this T target,Expression< Func< T,TValue> TValue值)
{
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


Given the following method:

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

How would you go about writing it's expression enabled equivalent without needing to pass in an extra parameter for target?

Why do this instead of setting the property directly I can hear you say. For example suppose we have the following class with a property that has a public getter but private setter:

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

I would like to be able to call:

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

Now here is some sample code.

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

}

Any pointers?

解决方案

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.

这篇关于如何使用表达式设置属性值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆