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?
In general, when we try to copy one object to another object, both the objects will share the same memory address. Normally, we use assignment operator, = , to copy the reference, not the object except when there is value type field. This operator will always copy the reference, not the actual object.
Property(Expression, String)Creates a MemberExpression that represents accessing a property. public: static System::Linq::Expressions::MemberExpression ^ Property(System::Linq::Expressions::Expression ^ expression, System::String ^ propertyName); C# Copy. public static System.Linq.Expressions.
An expression-bodied method consists of a single expression that returns a value whose type matches the method's return type, or, for methods that return void , that performs some operation.
There are some rules you need to be aware of when you are using expression-bodied members in a class: The visibility of these members can only be public, protected, internal, private, and protected internal. You are able to declare members virtual or abstract. Members are capable of overriding base class methods.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With