Implemented Pluck/Select to extract a given property from a DynamicNodeList and return it as a List<T>
Example:
var colours = @Model.Children.Select("colour");
//Red, Green, Blue ...
Uses the parser from .Where internally
Aliased as .Pluck
This commit is contained in:
@@ -48,6 +48,54 @@ namespace umbraco.MacroEngines
|
||||
result = new DynamicNodeList(this.OrderBy<DynamicNode>(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<object>)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<string>)itemsOfDominantTypeOnly.Cast<string>().ToList();
|
||||
}
|
||||
else if (dominantType == typeof(int))
|
||||
{
|
||||
result = (List<int>)itemsOfDominantTypeOnly.Cast<int>().ToList();
|
||||
}
|
||||
else if (dominantType == typeof(decimal))
|
||||
{
|
||||
result = (List<decimal>)itemsOfDominantTypeOnly.Cast<decimal>().ToList();
|
||||
}
|
||||
else if (dominantType == typeof(bool))
|
||||
{
|
||||
result = (List<bool>)itemsOfDominantTypeOnly.Cast<bool>().ToList();
|
||||
}
|
||||
else if (dominantType == typeof(DateTime))
|
||||
{
|
||||
result = (List<DateTime>)itemsOfDominantTypeOnly.Cast<DateTime>().ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = query.ToList();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
try
|
||||
{
|
||||
//Property?
|
||||
@@ -161,14 +209,18 @@ namespace umbraco.MacroEngines
|
||||
return Items.GetEnumerator();
|
||||
}
|
||||
|
||||
public IQueryable<T> Where<T>(string predicate, params object[] values)
|
||||
private IQueryable<T> Where<T>(string predicate, params object[] values)
|
||||
{
|
||||
return ((IQueryable<T>)Items.AsQueryable()).Where(predicate, values);
|
||||
}
|
||||
public IQueryable<T> OrderBy<T>(string key)
|
||||
private IQueryable<T> OrderBy<T>(string key)
|
||||
{
|
||||
return ((IQueryable<T>)Items.AsQueryable()).OrderBy(key);
|
||||
}
|
||||
private IQueryable Select(string predicate, params object[] values)
|
||||
{
|
||||
return DynamicQueryable.Select(Items.AsQueryable(), predicate, values);
|
||||
}
|
||||
|
||||
public void Add(DynamicNode node)
|
||||
{
|
||||
|
||||
@@ -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<DynamicNode> 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<object>
|
||||
IQueryable<DynamicNode> typedSource = source as IQueryable<DynamicNode>;
|
||||
var compiledFunc = lambda.Compile();
|
||||
Func<DynamicNode, object> func = null;
|
||||
if (compiledFunc is Func<DynamicNode, object>)
|
||||
{
|
||||
func = (Func<DynamicNode, object>)compiledFunc;
|
||||
}
|
||||
return typedSource.Select(delegate(DynamicNode node)
|
||||
{
|
||||
object value = null;
|
||||
value = func(node);
|
||||
if (value is Func<DynamicNode, object>)
|
||||
{
|
||||
var innerValue = (value as Func<DynamicNode, object>)(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<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values)
|
||||
|
||||
Reference in New Issue
Block a user