考虑以下类:
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/