Expression <Func <T>> Property Selector. How to get / set the value for the selected property

I have an object that I want to build in this way:

var foo = new FancyObject(customer, c=>c.Email); //customer has Email property 

How to declare the second parameter?

What will the code look like that will access the selected device / property recipient?

Upd. There are several objects in the model that have the Email property. The signature will probably look like this:

 public FancyObject(Entity holder, Expression<Func<T>> selector) 

and constructor call

 var foo = new FancyObject(customer, ()=>customer.Email); 
+50
c #
Feb 22 '11 at 7:55
source share
2 answers

The parameter will be Expression<Func<Customer,string>> selector . Reading can be done using flat compilation:

  Func<Customer,string> func = selector.Compile(); 

then you can access func(customer) . Appointment is more complicated; for simple selectors, you can hope that you can simply decompose into:

 var prop = (PropertyInfo)((MemberExpression)selector.Body).Member; prop.SetValue(customer, newValue, null); 

However, for more complex expressions, you will need either a manual tree-like movement or some 4.0 node -types expression:

  Expression<Func<Customer, string>> email = cust => cust.Email; var newValue = Expression.Parameter(email.Body.Type); var assign = Expression.Lambda<Action<Customer, string>>( Expression.Assign(email.Body, newValue), email.Parameters[0], newValue); var getter = email.Compile(); var setter = assign.Compile(); 
+87
Feb 22 2018-11-11T00:
source share

It seems that the type should be shared with two type parameters - the source and the result. For example, you can use:

 var foo = new FancyObject<Customer, string>(customer, c => c.Email); 

The first parameter will be of type TSource , and the second will be Expression<Func<TSource, TResult>> :

 public class FancyObject<TSource, TResult> { private readonly TSource value; private readonly Expression<Func<TSource, TResult>> projection; public FancyObject(TSource value, Expression<Func<TSource, TResult>> projection) { this.value = value; this.projection = projection; } } 

You can make it easier to use with a static method in a nonequivalent type:

 var foo = FancyObject.Create(customer, c => c.Email); 

This can use type inference to determine type arguments.

+6
Feb 22 2018-11-11T00:
source share



All Articles