Josh
Josh

Reputation: 16532

Using Linq to select property using an expression

I have an object like this:

public class Sheet
{
    public decimal? Value1 { get; set; }
    public decimal? Value2 { get; set; }
}

I have a linq query that builds a list of Tuple<int, Sheet>. The int is a percentage value stored in our database. This could be a wrapper class, but for simplicity I am using a Tuple.

Then I have an extension method

public static decimal CalculateValue(this List<Tuple<int, Sheet>> sheets, Expression<Func<Tuple<int, Sheet>, decimal?>> field)
{
    //return sum of int / 100 * field
}

What I want to do is call something like this (list actually built from objects using linq)

List<Tuple<int, Sheet>> sheets = new List<Tuple<int, Sheet>>();

var value1 = sheets.CalculateValue(x => x.Value1);
var value2 = sheets.CalculateValue(x => x.Value2);

I do not want to use reflection. I do not want "magic" strings for the properties Value1 or Value2. Is there a way for my extension method to grab the property using the expression and then multiply it by the percentage, and then sum the result across the collection?

Upvotes: 0

Views: 251

Answers (1)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236188

According to API which you are trying to build, you should pass property selector for Sheet object, not for Tuple<int, Sheet>. You also can use simple Func delegate instead of expression, because you are working with in-memory objects.

It's not clear how you are going to handle null values - it definitely makes no sense to multiply by null, so I just use zero instead of null (such values will not affect sum):

public static decimal CalculateValue(
    this List<Tuple<int, Sheet>> sheets, Func<Sheet, decimal?> field)
{
    return sheets.Sum(t => t.Item1 * field(t.Item2).GetValueOrDefault() / 100);
}

Keep in mind - when you apply division operator on two integers, integer division is used. If Item1 value is less than 100, this division will produce 0 as result. That's why I put multiplication operator first.

Upvotes: 1

Related Questions