给定以下列表:
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/