使用Linq使用表达式选择属性

时间:2014-06-23 22:26:29

标签: c# linq

我有一个这样的对象:

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

我有一个linq查询,用于构建Tuple<int, Sheet>列表。 int是存储在我们的数据库中的百分比值。这可能是一个包装类,但为了简单起见,我使用的是元组。

然后我有一个扩展方法

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

我想要做的是调用类似的东西(列表实际上是使用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);

我不想使用反射。我不希望属性Value1Value2使用“魔术”字符串。我的扩展方法是否有办法使用表达式获取属性,然后将其乘以百分比,然后将结果汇总到集合中?

1 个答案:

答案 0 :(得分:1)

根据您要构建的API,您应该为Sheet对象传递属性选择器,而不是Tuple<int, Sheet>。您还可以使用简单的Func委托而不是表达式,因为您正在使用内存中的对象。

目前尚不清楚你将如何处理空值 - 以null为单位绝对没有意义,所以我只使用零而不是null(这样的值不会影响总和):

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);
}

请记住 - 当您对两个整数应用除法运算符时,会使用integer division。如果Item1值小于100,则此除法将生成0。这就是为什么我把乘法算子放在首位。