From 1b060dfdbf7fce52b147ca98f9028e49d0c8ce8b Mon Sep 17 00:00:00 2001 From: "agrath@gmail.com" Date: Sat, 12 Mar 2011 16:29:02 -1300 Subject: [PATCH] Implemented Pluck/Select to extract a given property from a DynamicNodeList and return it as a List Example: var colours = @Model.Children.Select("colour"); //Red, Green, Blue ... Uses the parser from .Where internally Aliased as .Pluck --- .../RazorDynamicNode/DynamicNodeList.cs | 56 ++++++++++++++++++- .../RazorDynamicNode/DynamicQueryable.cs | 39 ++++++++++--- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNodeList.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNodeList.cs index 2645ef2bff..0a9e3e7729 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNodeList.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNodeList.cs @@ -48,6 +48,54 @@ namespace umbraco.MacroEngines result = new DynamicNodeList(this.OrderBy(args.First().ToString()).ToList()); 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(); + } + } + return true; + } try { //Property? @@ -161,14 +209,18 @@ namespace umbraco.MacroEngines return Items.GetEnumerator(); } - public IQueryable Where(string predicate, params object[] values) + private IQueryable Where(string predicate, params object[] values) { return ((IQueryable)Items.AsQueryable()).Where(predicate, values); } - public IQueryable OrderBy(string key) + private IQueryable OrderBy(string key) { return ((IQueryable)Items.AsQueryable()).OrderBy(key); } + private IQueryable Select(string predicate, params object[] values) + { + return DynamicQueryable.Select(Items.AsQueryable(), predicate, values); + } public void Add(DynamicNode node) { diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs index 3c5fc9cc0d..0a89ab0e1a 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs @@ -89,16 +89,41 @@ namespace System.Linq.Dynamic } } - public static IQueryable Select(this IQueryable source, string selector, params object[] values) + public static IQueryable Select(this IQueryable source, string selector, params object[] values) { if (source == null) throw new ArgumentNullException("source"); if (selector == null) throw new ArgumentNullException("selector"); - LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, values); - return source.Provider.CreateQuery( - Expression.Call( - typeof(Queryable), "Select", - new Type[] { source.ElementType, lambda.Body.Type }, - source.Expression, Expression.Quote(lambda))); + LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(object), selector, values); + if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicNode)) + { + //source list is DynamicNode and the lambda returns a Func + IQueryable typedSource = source as IQueryable; + var compiledFunc = lambda.Compile(); + Func func = null; + if (compiledFunc is Func) + { + func = (Func)compiledFunc; + } + return typedSource.Select(delegate(DynamicNode node) + { + object value = null; + value = func(node); + if (value is Func) + { + var innerValue = (value as Func)(node); + return innerValue; + } + return value; + }).AsQueryable(); + } + else + { + return source.Provider.CreateQuery( + Expression.Call( + typeof(Queryable), "Select", + new Type[] { source.ElementType, lambda.Body.Type }, + source.Expression, Expression.Quote(lambda))); + } } public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values)