Как установить значение свойства с помощью выражений?
Учитывая следующий метод:
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);
}
Как вы могли бы использовать выражение, эквивалентное выражению, без необходимости передавать дополнительный параметр для цели?
Зачем это делать вместо того, чтобы напрямую устанавливать свойство, я слышу, как вы говорите. Например, предположим, что у нас есть следующий класс с свойством, имеющим открытый геттер, но частный сеттер:
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
}
Любые указатели?
Ответы
Ответ 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");
Причина, по которой это проще, состоит в том, что у вас уже есть цель, на которую вызывается метод расширения. Кроме того, лямбда-выражение представляет собой простое выражение члена без замыканий. В вашем исходном примере цель захвачена в закрытии, и может быть немного сложно добраться до основной цели и PropertyInfo
.