Friday, 13 February 2015

LINQ: Dynamic Groupby, OrderBy, and Dynamic Aggregates.

How to dynamically achieve groupby, orderby and aggregates using LINQ ?
huh.. what..? Is it is possible.. yes it is.. Here is the solution.

Here are some of our helper methods:

private static object GetPropertyValue(object obj, string propertyName)
        {
            return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
        }
private static double GetPropertyValueDouble(object obj, string propertyName)
        {
            double ret = Convert.ToDouble(obj.GetType().GetProperty(propertyName).GetValue(obj, null));
            return ret;
        }
Consider below sample example:
 public class test
    {
        public string City { get; set; }
        public string Name { get; set; }
        public string State { get; set; }
        public double Cost { get; set; }
    } 
          List<test> xxx = new List<test>(){
                            new test(){City="MNG",Name="Jhon",State="KNK",Cost=10},
                            new test(){City="MNG",Name="Jhon",State="KNK",Cost=19},
                            new test(){City="BLR",Name="Jhon",State="DL",Cost=66},
                            new test(){City="BLR",Name="Jhon",State="DL",Cost=67},
                            new test(){City="BLR",Name="Jhon",State="DL",Cost=67}
                        };

                    switch (aggregate)
                    {
                        case "Count":
                            var grouped1 = xxx.GroupBy(x => GetPropertyValue(x, "City"))
                                            .Select(n => new
                                            {
                                                EntityName = n.Key,
                                                TotalCost = n.Count()
                                            });
                            return grouped1;
                        case "Sum":
                            var grouped2 = xxx.GroupBy(x => GetPropertyValue(x, "City"))
                                            .Select(n => new
                                            {
                                                EntityName = n.Key,
                                                TotalCost = n.Sum(a => GetPropertyValueDouble(a, "Cost"))
                                            });
                            return grouped2;
                        case "Average":
                            var grouped3 = xxx.GroupBy(x => GetPropertyValue(x, "City"))
                                             .Select(n => new
                                             {
                                                 EntityName = n.Key,
                                                 TotalCost = n.Average(a => GetPropertyValueDouble(a, "Cost"))
                                             });
                            return grouped3;

                        default:
                            break;
                    }

Hope it helped you. :)