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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9601707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 08:04:16  来源:igfitidea点击:

How to set property value using Expressions?

c#linqexpression

提问by Anastasiosyal

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:

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

任何指针?

采纳答案by Darin Dimitrov

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.

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