diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNodeList.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNodeList.cs index ce2468897e..e8c4e0f594 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNodeList.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNodeList.cs @@ -82,53 +82,14 @@ namespace umbraco.MacroEngines result = this.GroupBy(args.First().ToString()); return true; } - + if (name == "Average" || name == "Min" || name == "Max" || name == "Sum") + { + result = Aggregate(args, name); + return true; + } if (name == "Pluck" || name == "Select") { - string predicate = args.First().ToString(); - var values = args.Skip(1).ToArray(); - var query = (IQueryable)this.Select(predicate, values); - object firstItem = query.FirstOrDefault(); - if (firstItem == null) - { - result = new DynamicNull(); - } - else - { - var types = from i in query - group i by i.GetType() into g - orderby g.Count() descending - select new { g, Instances = g.Count() }; - var dominantType = types.First().g.Key; - //remove items that are not the dominant type - //e.g. string,string,string,string,false[DynamicNull],string - var itemsOfDominantTypeOnly = query.ToList(); - itemsOfDominantTypeOnly.RemoveAll(item => !item.GetType().IsAssignableFrom(dominantType)); - if (dominantType == typeof(string)) - { - result = (List)itemsOfDominantTypeOnly.Cast().ToList(); - } - else if (dominantType == typeof(int)) - { - result = (List)itemsOfDominantTypeOnly.Cast().ToList(); - } - else if (dominantType == typeof(decimal)) - { - result = (List)itemsOfDominantTypeOnly.Cast().ToList(); - } - else if (dominantType == typeof(bool)) - { - result = (List)itemsOfDominantTypeOnly.Cast().ToList(); - } - else if (dominantType == typeof(DateTime)) - { - result = (List)itemsOfDominantTypeOnly.Cast().ToList(); - } - else - { - result = query.ToList(); - } - } + result = Pluck(args); return true; } try @@ -194,6 +155,142 @@ namespace umbraco.MacroEngines } } + private T Aggregate(List data, string name) where T : struct + { + switch (name) + { + case "Min": + return data.Min(); + case "Max": + return data.Max(); + case "Average": + if (typeof(T) == typeof(int)) + { + return (T)Convert.ChangeType((data as List).Average(), typeof(T)); + } + if (typeof(T) == typeof(decimal)) + { + return (T)Convert.ChangeType((data as List).Average(), typeof(T)); + } + break; + case "Sum": + if (typeof(T) == typeof(int)) + { + return (T)Convert.ChangeType((data as List).Sum(), typeof(T)); + } + if (typeof(T) == typeof(decimal)) + { + return (T)Convert.ChangeType((data as List).Sum(), typeof(T)); + } + break; + } + return default(T); + } + private object Aggregate(object[] args, string name) + { + object result; + string predicate = args.First().ToString(); + var values = args.Skip(1).ToArray(); + var query = (IQueryable)this.Select(predicate, values); + object firstItem = query.FirstOrDefault(); + if (firstItem == null) + { + result = new DynamicNull(); + } + else + { + var types = from i in query + group i by i.GetType() into g + orderby g.Count() descending + select new { g, Instances = g.Count() }; + var dominantType = types.First().g.Key; + //remove items that are not the dominant type + //e.g. string,string,string,string,false[DynamicNull],string + var itemsOfDominantTypeOnly = query.ToList(); + itemsOfDominantTypeOnly.RemoveAll(item => !item.GetType().IsAssignableFrom(dominantType)); + if (dominantType == typeof(string)) + { + throw new ArgumentException("Can only use aggregate methods on properties which are numeric"); + } + else if (dominantType == typeof(int)) + { + List data = (List)itemsOfDominantTypeOnly.Cast().ToList(); + return Aggregate(data, name); + } + else if (dominantType == typeof(decimal)) + { + List data = (List)itemsOfDominantTypeOnly.Cast().ToList(); + return Aggregate(data, name); + } + else if (dominantType == typeof(bool)) + { + throw new ArgumentException("Can only use aggregate methods on properties which are numeric or datetime"); + } + else if (dominantType == typeof(DateTime)) + { + if (name != "Min" || name != "Max") + { + throw new ArgumentException("Can only use aggregate min or max methods on properties which are datetime"); + } + List data = (List)itemsOfDominantTypeOnly.Cast().ToList(); + return Aggregate(data, name); + } + else + { + result = query.ToList(); + } + } + return result; + } + private object Pluck(object[] args) + { + object result; + string predicate = args.First().ToString(); + var values = args.Skip(1).ToArray(); + var query = (IQueryable)this.Select(predicate, values); + object firstItem = query.FirstOrDefault(); + if (firstItem == null) + { + result = new DynamicNull(); + } + else + { + var types = from i in query + group i by i.GetType() into g + orderby g.Count() descending + select new { g, Instances = g.Count() }; + var dominantType = types.First().g.Key; + //remove items that are not the dominant type + //e.g. string,string,string,string,false[DynamicNull],string + var itemsOfDominantTypeOnly = query.ToList(); + itemsOfDominantTypeOnly.RemoveAll(item => !item.GetType().IsAssignableFrom(dominantType)); + if (dominantType == typeof(string)) + { + result = (List)itemsOfDominantTypeOnly.Cast().ToList(); + } + else if (dominantType == typeof(int)) + { + result = (List)itemsOfDominantTypeOnly.Cast().ToList(); + } + else if (dominantType == typeof(decimal)) + { + result = (List)itemsOfDominantTypeOnly.Cast().ToList(); + } + else if (dominantType == typeof(bool)) + { + result = (List)itemsOfDominantTypeOnly.Cast().ToList(); + } + else if (dominantType == typeof(DateTime)) + { + result = (List)itemsOfDominantTypeOnly.Cast().ToList(); + } + else + { + result = query.ToList(); + } + } + return result; + } private object ExecuteExtensionMethod(object[] args, string name, bool argsContainsThis) {