Consider the following class:
public class TaxType
{
public int Id {get;set;}
public decimal TotalTaxCollected {get;set;}
public string DetailXml {get;set;}
}
I got the following LINQ query somewhere in the code:
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();
Where SumOfInnerElementsOfXml is declared as follows:
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)
}
The above solution works fine, however I'd like to create my own aggregate function so that I can use it as follows:
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();
How's that possible? I've tried several extension methods but unfortunately none of them worked.
Your initial solution seems pretty fine to me. However, if you don't like it...
To create a predefined function (not lambda), I'd recommend first to get rid of anonymous type in your query - change:
.GroupBy(t => new { t.Id })
to
.GroupBy(t => t.Id)
This is also generally better, as you get rid of one boxing/unboxing per TaxType and transform IGrouping<{anonymous},TaxType> into IGrouping<int,TaxType> (easier to understand the semantics if someone inspects the code later)
Then, you can declare the method as follows:
public static class Extensions {
public static string MyCustomAggregateFunction(this IGrouping<int,TaxType> source, Func<TaxType,string> selector) {
// blah-blah-blah
//return something
}
}
You can later make it generic if the need arises.
I'd also recommend getting rid of the dependency on IGrouping, as you later may need to apply that aggregation elsewhere:
TotalTaxCollected = g.Sum(n => n.TotalTaxCollected),
DetailXml = g.Select(n => n.DetailXml).AggregateTaxXML()
and
public static string AggregateTaxXML(this IEnumerable<string> source) {
// blah-blah-blah
//return something
}
Sources/further reading: MSDN
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With