I have several functions that takes in list of objects and create a chart Series out of them. It looks repetetive and I feel like I can replace these similar looking functions with Lambda expressions or templates, but haven't been able to figure out how to deal with the different property names on each object. Can someone help?
Here's what I have:
private static Series getBuysSeries(List<Order> buys)
{
var series = new Series();
foreach (var buy in buys)
{
series.Points.AddXY(buy.Price, buy.Quantity);
}
return series;
}
private Series getPriceSeries(List<Trade> trades)
{
var series = new Series();
foreach (var trade in trades)
{
series.Points.AddXY(trade.DateTimeUTC, trade.UnitPrice);
}
return series;
}
I would think it could look like:
private static Series getBuysSeries(List<Order> buys)
{
return getSeries<Order>(buys);
}
private Series getPriceSeries(List<Trade> trades)
{
return getSeries<Trade>(trades);
}
private Series getSeries<T>(List<T> list)
{
...do the loop but account for property names...
}
Yes, you can. At least, you may be able to. For example - having changed the method names to be more conventional, and using generic type inference for the method calls:
private static Series GetBuysSeries(List<Order> buys)
{
return GetSeries(buys, buy => buy.Price, buy => buy.Quantity);
}
private Series GetPriceSeries(List<Trade> trades)
{
return getSeries<Trade>(trades,
trade => trade.DateTimeUtc,
trade => trade.UnitPrice);
}
private Series GetSeries<T>(List<T> list,
Func<T, double> selector1,
Func<T, double> selector2)
{
var series = new Series();
foreach (var item in list)
{
series.Points.AddXY(selector1(item), selector2(item));
}
return series;
}
Now that's assuming that AddXY
takes two double
values. That seems a little odd for trade.DateTimeUTC
, but it's hard to give more specific advice without knowing how Series.AddXY
is defined.
If you actually want to call a different overload of AddXY
in each case, it'll be a bit trickier. In that case you may need to use dynamic typing, e.g.
private Series GetSeries<T>(List<T> list,
Func<T, dynamic> selector1,
Func<T, dynamic> selector2)
{
var series = new Series();
foreach (var item in list)
{
// Here the overload is determined at execution time...
series.Points.AddXY(selector1(item), selector2(item));
}
return series;
}
See more on this question at Stackoverflow