Llarian
Llarian

Reputation: 81

Get Func<T1, T2> from PropertyInfo

I am stuck at the following problem:
I have a class like

public class DataItem
{
    public decimal? ValueA{ get; set; }
    public decimal? ValueB { get; set; }
    public decimal? valueC { get; set; }
    ...
}

and would like to have something like

 var keySelectors = new Dictionary<string, Func<DataItem, decimal?>>
 {
     {"ValueA", x => x.ValueA},
     {"ValueB", x => x.ValueB},
     {"ValueC", x => x.ValueC},
     ...
 }.ToList();

to be used for a user defined analysis, but I need a more generic way to create it.
So I tried the following:

var keySelectors= typeof(DataItem).GetProperties()
  .Select(x => new KeyValuePair<string, Func<DataItem, decimal?>>(x.Name, x.DoNotKnow));

the DoNotKnow is the point where I am lost.

Or is this a wrong approach for the desired result to enable the user to choose the data on which his analysis is based?

Upvotes: 0

Views: 201

Answers (3)

Avestura
Avestura

Reputation: 1557

A human readable solution:

Func<DataItem, decimal?> GetValue(PropertyInfo p) => (item) => (decimal?)(p.GetValue(item));

var keySelctors =  typeof(DataItem).GetProperties().ToDictionary(p => p.Name, GetValue);

Upvotes: 0

Mike Zboray
Mike Zboray

Reputation: 40788

What you want to do is create a delegate to an instance method, the property's getter method. This can be done with CreateDelegate:

var props = typeof(DataItem).GetProperties()
    .Select(x => new KeyValuePair<string, Func<DataItem, decimal?>>(x.Name,
     (Func<DataItem, decimal?>)x.GetGetMethod().CreateDelegate(typeof(Func<DataItem, decimal?>))));

Invoking a delegate is faster than doing this using the reflection-based method, GetValue on PropertyInfo, but obviously the impact depends on your scenario.

Upvotes: 2

Sergei Z
Sergei Z

Reputation: 535

Here's one way:

typeof(DataItem).GetProperties()
    .Select(p => new KeyValuePair<string, Func<DataItem, decimal?>>(
        p.Name,
        item => (decimal?)typeof(DataItem).InvokeMember(p.Name, BindingFlags.GetProperty, null, item, null)
    ));

Upvotes: 0

Related Questions