c# - 使用 Dynamic Linq 库运行总和

标签 c# linq dynamic-linq

给定以下列表:

var items = new List<int> { 1, 2, 3, 5 };

我正在尝试使用 Dynamic Linq library 计算任何给定记录的先前记录总数.在标准 LINQ(LINQ to Objects)中,我可以这样做:

var runningTotal = 0;
var qry1 = items.Select(x => {
    var ret = new { x, runningTotal };
    runningTotal += x;
    return ret;
});

或者这个(效率较低,因为它每次都遍历列表中的所有先前项目。对于这么小的列表来说这显然不是问题,但对于更大的列表来说会是这样):

var qry1 = items.Select((x, idx) => new { 
    x, 
    runningTotal = items.Take(idx).Sum()
});

库没有实现 Take在字符串表达式中,或重载 Select它采用元素的索引。然而,以下内容几乎到达那里:

var qry2 = items.AsQueryable().Select(
    "new(it as x, @0.Where(it < parent).Sum(it) as runningTotal)",
    items
);

但是,这有一些缺点:

  • 列表必须有一定的顺序,否则内部 Where将返回任意记录
  • 同理,每件元素都必须是独一无二的
  • 这与第二个 C# 示例一样效率低下

有没有什么方法可以使用不存在这些问题的 Dynamic Linq 来做到这一点,如果可以,那么怎么做?


更新

我尝试编写以下类:

[DynamicLinqType]
public class Aggregator<T> {
    private T state;
    private Func<T, T, T> fn;
    public Aggregator(Func<T, T, T> fn) {
        this.fn = fn;
    }
    public T GetState(T value) {
        state = fn(state, value);
        return state;
    }
}

然后像这样查询:

var aggregator = new Aggregator<int>((runningTotal1, x) => runningTotal1 + x);
var qry4 = items.AsQueryable().Select(
    "new(it as x, @0.GetState(it) - it as runningTotal)", 
    aggregator
);

但我得到一个 ParseException: Methods on type 'Aggregator1' are not accessible即使 GetState方法是公开的。这是因为该库将自身限制为仅使用某些预定义类型的成员,以及标有 DynamicLinqTypeAttribute 的类型。 (默认情况下)。但是标记的类型 Aggregator<T>与构造类型 ( Aggregator<int> ) 不同。


更新 2

我已经提交了 issue about running calculations和另一个关于 generic combinations of recognized types 的问题.

最佳答案

我做了一些研究,发现错误在哪里:

DynamicLinqType注册类型 - 在你的情况下 Aggregator<T>

所以当你指定 T int 这已经是另一种类型了 Aggregator<int> , 和 DynamicLinq认为它不是预定义的类型。

因此,作为解决方案,您可以删除通用部分:

[DynamicLinqType]
public class Aggregator
{
    private int state;
    private Func<int, int, int> fn;
    public Aggregator(Func<int, int, int> fn)
    {
        this.fn = fn;
    }
    public int GetState(int value)
    {
        state = fn(state, value);
        return state;
    }
}

更新:
还有另一种方法 - 在源代码中修复此问题:

static bool IsPredefinedType(Type type)
{
    if (_predefinedTypes.Contains(type)) return true;

    if (GlobalConfig.CustomTypeProvider.GetCustomTypes().Contains(type)) return true;

    // for generic type check GenericTypeDefinition
    if (type.IsGenericType && GlobalConfig.CustomTypeProvider.GetCustomTypes().Contains(type.GetGenericTypeDefinition())) return true;

    return false;
}

关于c# - 使用 Dynamic Linq 库运行总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33556712/

相关文章:

javascript - FullCalendar 中的工具提示

java - 在无符号字节变量中表示有符号字节

c# - LINQ - 仅列出最低价格

c# - 如何创建一个 linq 语句来获取项目列表并将它们分成每组 50 个

c# - 动态 Linq + Entity Framework : datetime modifications for dynamic select

c# - 如何在工作线程中从 UI 线程获取变量?

c# - 多页 PDF 在 iPad 上无法打开

c# - 无法在 LINQ C# 中排序和删除重复项

c# - linq c#中的动态字符串

c# - 如何使用 Dynamic Linq 进行左外连接?