c# - 使用 LINQ 在 C# 中创建自定义聚合函数

标签 c# linq c#-4.0

考虑以下类:

public class TaxType
{
    public int Id {get;set;}
    public decimal TotalTaxCollected {get;set;}
    public string DetailXml {get;set;}
}

我在代码的某处得到以下 LINQ 查询:

GetTaxTypesFromTheDataSource()
.Where(/*blah blah blah*/)
.GroupBy(t => new { t.Id })
.Select(g => new TaxType
{
    TotalTaxCollected = g.Sum(n => n.TotalTaxCollected),
    DetailXml = g.Aggregate(SumOfInnerElementsOfXml).DetailXml
})
.ToList();

其中 SumOfInnerElementsOfXml 声明如下:

private TaxType SumOfInnerElementsOfXml(TaxType t1, TaxType t2)
{
    //(a) Deserialize the t1.DetailXml & t2.DetailXml into 2 different arrays.
    //(b) Aggregate both arrays based on their IDs.
    //(c) Serialize the result into an xml string.
    //(d) Instantiate a new TaxType and set its DetailXml to the generated xml string.
    //return (d)
}

上述解决方案工作正常,但我想创建自己的聚合函数,以便我可以按如下方式使用它:

GetTaxTypesFromTheDataSource()
.Where(/*blah blah blah*/)
.GroupBy(t => new { t.Id })
.Select(g => new TaxType
{
    TotalTaxCollected = g.Sum(n => n.TotalTaxCollected),
    DetailXml = g.MyCustomAggregateFunction(n => n.DetailXml)
})
.ToList();

这怎么可能?我尝试了几种扩展方法,但不幸的是,它们都不起作用。

最佳答案

您的初始解决方案对我来说似乎还不错。但是,如果您不喜欢它...

要创建一个预定义的函数(不是 lambda),我建议首先摆脱查询中的匿名类型 - 更改:

.GroupBy(t => new { t.Id })

.GroupBy(t => t.Id)

这通常也更好,因为您摆脱了每个 TaxType 的一次装箱/拆箱并转换 IGrouping<{anonymous},TaxType>进入IGrouping<int,TaxType> (如果有人稍后检查代码,更容易理解语义)

然后,你可以声明方法如下:

public static class Extensions {
    public static string MyCustomAggregateFunction(this IGrouping<int,TaxType> source, Func<TaxType,string> selector) {
        // blah-blah-blah
        //return something
    }
}

如果需要,您可以稍后将其设为通用。

我还建议摆脱对 IGrouping 的依赖,因为您以后可能需要在其他地方应用该聚合:

TotalTaxCollected = g.Sum(n => n.TotalTaxCollected),
DetailXml = g.Select(n => n.DetailXml).AggregateTaxXML()

public static string AggregateTaxXML(this IEnumerable<string> source) {
    // blah-blah-blah
    //return something
}

来源/进一步阅读:MSDN

关于c# - 使用 LINQ 在 C# 中创建自定义聚合函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20372119/

相关文章:

c# - 如何在 ItextSharp(PdfStamper) 中增加 PDF 字段的字体大小?

c# - 将标准输出重定向到列表<string>或流

c# - 如何投影OpenGL控件的顶部和底部区域(圆柱投影)?

c# - 使用公钥解密

c# - Linq Contains 不考虑口音

c# - 难以为 System.Linq.Enumerable.Select 输入参数

c#-4.0 - C# - 如何获取 cpu、内存和磁盘使用率(如任务管理器中所示)

c# - Unity3d - 将 Material 设置为无

c# - 合并两个列表列表

c# - 在并行数据处理中使用什么类型的队列 - C# - .NET 4