考虑以下课程:
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();
怎么可能?我尝试了几种扩展方法,但不幸的是它们都没有。
答案 0 :(得分:3)
您的初始解决方案对我来说似乎很好。但是,如果你不喜欢它......
要创建预定义函数(不是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