1. ホーム
  2. c#

エクスプレッションを使用してプロパティ値を設定する方法は?重複

2023-11-23 16:18:02

質問

次のようなメソッドがあるとします。

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

targetに余分なパラメータを渡すことなく、これと同等の式を書くにはどうしたらよいでしょうか。

プロパティを直接設定する代わりに、なぜこのようなことをするのでしょうか?たとえば、次のようなクラスで、パブリックゲッターとプライベートセッターを持つプロパティがあるとします。

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

}

何かご指摘は?

どのように解決するのですか?

拡張メソッドでごまかして楽をするのも手です。

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

なぜこの方法が簡単かというと、拡張メソッドの呼び出し先がすでに決まっているからです。また、ラムダ式はクロージャを使わない単純なメンバ式です。元の例では、ターゲットはクロージャに取り込まれており、根本的なターゲットに到達するのは少し難しいかもしれません。 PropertyInfo .