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

C# 如何使用表达式设置属性值?,c#,linq,expression,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 | Bind

根据以下方法:

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");
var myCustomerInstance=new Customer();
SetPropertyValue(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

}
publicstaticvoid SetPropertyValue(表达式memberLamda,对象值)
{
MemberExpression memberSelectorExpression;
var selectorExpression=memberLamda.Body;
var castExpression=选择或表达为一元表达式;
if(castExpression!=null)
memberSelectorExpression=castExpression。操作数作为MemberExpression;
其他的
memberSelectorExpression=memberLamda.Body作为MemberExpression;
//如何获取myCustomerInstance的值,以便调用SetValue并将其作为参数传入?是否可能
}

有什么建议吗

通过扩展方法,你可以作弊,让生活更轻松:

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

这之所以更容易,是因为您已经有了调用扩展方法的目标。此外,lambda表达式是一个没有闭包的简单成员表达式。在最初的示例中,目标是在闭包中捕获的,要到达底层目标和
PropertyInfo

为什么要这样做?如果属性有一个私有setter,那么就不能从对象外部更改它!您提议的函数破坏了程序的语义。@VladislavZorov我可以看到这样的评论,我同意您的观点。在这种情况下,第三方DTO需要在单元测试中启动,这是最简单的方法。反射也有它的用途。Property.SetValue的可能副本是反射。你不应该使用它。这似乎不适用于嵌套对象,你知道我如何解决这个问题吗?你可以对值类型使用泛型类型:
publicstaticvoidsetpropertyvalue(这个t目标,表达式memberLamda,TValue值){var memberSelectorExpression=memberLamda.Body作为MemberExpression;if(memberSelectorExpression!=null){var property=memberSelectorExpression.Member作为PropertyInfo;if(property!=null){property.SetValue(target,value,null)}}
我在答案中加入了@pinus.acer的评论,因为它对我很有效。@Mboros:那么使用反射有什么不对?如果你进行了数百万次操作,可能速度很慢,但偶尔。。。
var myCustomerInstance = new Customer();
myCustomerInstance.SetPropertyValue(c => c.Title, "Mr");