Refactored the traversal, ishelper, etc... methods to be extension methods on IPublishedContent so now all of these methods are available on the Typed object not just the dynamic object which makes a whole lot more sense... and you can have intellisense.

Updated DynamicPublishedContent's methods to just proxy calls to the new extension methods so that all of the logic is contained in one place.
Added new GetRootDocuments to the IPublishedContentStore since we need this in order to get the root list of documents for many of these methods.
Fixed an issue with the DynamicNode to IPublishedContent converter.
Fixed many of the failing unit tests.
This commit is contained in:
Shannon Deminick
2012-10-04 01:31:08 +05:00
parent 831d1966dc
commit c0102f1c71
40 changed files with 2391 additions and 2120 deletions

View File

@@ -1,12 +1,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Collections;
using Umbraco.Core.Models;
namespace Umbraco.Core.Dynamics
{
public class DynamicGrouping : IEnumerable
{
internal IEnumerable<Grouping<object, DynamicPublishedContent>> Inner;
internal IEnumerable<Grouping<object, DynamicPublishedContentBase>> Inner;
public DynamicGrouping OrderBy(string expression)
{
@@ -21,7 +22,7 @@ namespace Umbraco.Core.Dynamics
.Select(node =>
{
string predicate = groupBy;
var internalList = new DynamicPublishedContentList(new DynamicPublishedContent[] { node });
var internalList = new DynamicPublishedContentList(new DynamicPublishedContentBase[] { node });
var query = (IQueryable<object>)internalList.Select(predicate, new object[] { });
var key = query.FirstOrDefault();
return new
@@ -32,13 +33,13 @@ namespace Umbraco.Core.Dynamics
})
.Where(item => item.Key != null)
.GroupBy(item => item.Key)
.Select(item => new Grouping<object, DynamicPublishedContent>()
.Select(item => new Grouping<object, DynamicPublishedContentBase>()
{
Key = item.Key,
Elements = item.Select(inner => inner.Node)
});
}
internal DynamicGrouping(IEnumerable<Grouping<object, DynamicPublishedContent>> source)
internal DynamicGrouping(IEnumerable<Grouping<object, DynamicPublishedContentBase>> source)
{
this.Inner = source;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +0,0 @@
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core.Dynamics
{
/// <summary>
/// This exists only because we want Dynamics in the Core project but DynamicNode has references to ContentType to run some queries
/// and currently the business logic part of Umbraco is still in the legacy project and we don't want to move that to the core so in the
/// meantime until the new APIs are made, we need to have this data source in place with a resolver which is set in the web project.
/// </summary>
internal class DynamicPublishedContentDataSourceResolver : SingleObjectResolverBase<DynamicPublishedContentDataSourceResolver, IDynamicPublishedContentDataSource>
{
public IDynamicPublishedContentDataSource DataSource { get; private set; }
public DynamicPublishedContentDataSourceResolver(IDynamicPublishedContentDataSource dataSource)
{
DataSource = dataSource;
}
}
}

View File

@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Core.Dynamics
{
internal class DynamicPublishedContentIdEqualityComparer : EqualityComparer<DynamicPublishedContent>
internal class DynamicPublishedContentIdEqualityComparer : EqualityComparer<DynamicPublishedContentBase>
{
public override bool Equals(DynamicPublishedContent x, DynamicPublishedContent y)
public override bool Equals(DynamicPublishedContentBase x, DynamicPublishedContentBase y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
@@ -20,7 +21,7 @@ namespace Umbraco.Core.Dynamics
}
public override int GetHashCode(DynamicPublishedContent obj)
public override int GetHashCode(DynamicPublishedContentBase obj)
{
if (Object.ReferenceEquals(obj, null)) return 0;

View File

@@ -1,504 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Dynamic;
using Umbraco.Core.Models;
using umbraco.interfaces;
using System.Collections;
using System.Reflection;
namespace Umbraco.Core.Dynamics
{
public class DynamicPublishedContentList : DynamicObject, IEnumerable<DynamicPublishedContent>
{
internal List<DynamicPublishedContent> Items { get; set; }
public DynamicPublishedContentList()
{
Items = new List<DynamicPublishedContent>();
}
public DynamicPublishedContentList(IEnumerable<DynamicPublishedContent> items)
{
List<DynamicPublishedContent> list = items.ToList();
list.ForEach(node => node.OwnerList = this);
Items = list;
}
public DynamicPublishedContentList(IEnumerable<IPublishedContent> items)
{
List<DynamicPublishedContent> list = items.Select(x => new DynamicPublishedContent(x)).ToList();
list.ForEach(node => node.OwnerList = this);
Items = list;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
int index = (int)indexes[0];
try
{
result = this.Items.ElementAt(index);
return true;
}
catch (IndexOutOfRangeException)
{
result = new DynamicNull();
return true;
}
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
//TODO: We MUST cache the result here, it is very expensive to keep finding extension methods and processing this stuff!
//TODO: Nowhere here are we checking if args is the correct length!
//NOTE: For many of these we could actually leave them out since we are executing custom extension methods and because
// we implement IEnumerable<T> they will execute just fine, however, to do that will be quite a bit slower than checking here.
var name = binder.Name;
if (name == "Where")
{
string predicate = args.First().ToString();
var values = args.Skip(1).ToArray();
//TODO: We are pre-resolving the where into a ToList() here which will have performance impacts if there where clauses
// are nested! We should somehow support an QueryableDocumentList!
result = new DynamicPublishedContentList(this.Where<DynamicPublishedContent>(predicate, values).ToList());
return true;
}
if (name == "OrderBy")
{
//TODO: We are pre-resolving the where into a ToList() here which will have performance impacts if there where clauses
// are nested! We should somehow support an QueryableDocumentList!
result = new DynamicPublishedContentList(this.OrderBy<DynamicPublishedContent>(args.First().ToString()).ToList());
return true;
}
if (name == "Take")
{
result = new DynamicPublishedContentList(this.Take((int)args.First()));
return true;
}
if (name == "Skip")
{
result = new DynamicPublishedContentList(this.Skip((int)args.First()));
return true;
}
if (name == "InGroupsOf")
{
int groupSize = 0;
if (int.TryParse(args.First().ToString(), out groupSize))
{
result = this.InGroupsOf<DynamicPublishedContent>(groupSize);
return true;
}
result = new DynamicNull();
return true;
}
if (name == "GroupedInto")
{
int groupCount = 0;
if (int.TryParse(args.First().ToString(), out groupCount))
{
result = this.GroupedInto<DynamicPublishedContent>(groupCount);
return true;
}
result = new DynamicNull();
return true;
}
if (name == "GroupBy")
{
result = this.GroupBy<DynamicPublishedContent>(args.First().ToString());
return true;
}
if (name == "Average" || name == "Min" || name == "Max" || name == "Sum")
{
result = Aggregate(args, name);
return true;
}
if (name == "Union")
{
if ((args.First() as IEnumerable<DynamicPublishedContent>) != null)
{
result = new DynamicPublishedContentList(this.Items.Union(args.First() as IEnumerable<DynamicPublishedContent>));
return true;
}
if ((args.First() as DynamicPublishedContentList) != null)
{
result = new DynamicPublishedContentList(this.Items.Union((args.First() as DynamicPublishedContentList).Items));
return true;
}
}
if (name == "Except")
{
if ((args.First() as IEnumerable<DynamicPublishedContent>) != null)
{
result = new DynamicPublishedContentList(this.Items.Except(args.First() as IEnumerable<DynamicPublishedContent>, new DynamicPublishedContentIdEqualityComparer()));
return true;
}
if ((args.First() as DynamicPublishedContentList) != null)
{
result = new DynamicPublishedContentList(this.Items.Except((args.First() as DynamicPublishedContentList).Items, new DynamicPublishedContentIdEqualityComparer()));
return true;
}
}
if (name == "Intersect")
{
if ((args.First() as IEnumerable<DynamicPublishedContent>) != null)
{
result = new DynamicPublishedContentList(this.Items.Intersect(args.First() as IEnumerable<DynamicPublishedContent>, new DynamicPublishedContentIdEqualityComparer()));
return true;
}
if ((args.First() as DynamicPublishedContentList) != null)
{
result = new DynamicPublishedContentList(this.Items.Intersect((args.First() as DynamicPublishedContentList).Items, new DynamicPublishedContentIdEqualityComparer()));
return true;
}
}
if (name == "Distinct")
{
result = new DynamicPublishedContentList(this.Items.Distinct(new DynamicPublishedContentIdEqualityComparer()));
return true;
}
if (name == "Pluck" || name == "Select")
{
result = Pluck(args);
return true;
}
try
{
//Property?
result = Items.GetType().InvokeMember(binder.Name,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.GetProperty,
null,
Items,
args);
return true;
}
catch (MissingMethodException)
{
try
{
//Static or Instance Method?
result = Items.GetType().InvokeMember(binder.Name,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Static |
System.Reflection.BindingFlags.InvokeMethod,
null,
Items,
args);
return true;
}
catch (MissingMethodException)
{
try
{
result = ExecuteExtensionMethod(args, name);
return true;
}
catch (TargetInvocationException)
{
//We do this to enable error checking of Razor Syntax when a method e.g. ElementAt(2) is used.
//When the Script is tested, there's no Children which means ElementAt(2) is invalid (IndexOutOfRange)
//Instead, we are going to return an empty DynamicNode.
result = DynamicPublishedContent.Empty();
return true;
}
catch
{
result = null;
return false;
}
}
}
catch
{
result = null;
return false;
}
}
private T Aggregate<T>(List<T> data, string name) where T : struct
{
switch (name)
{
case "Min":
return data.Min<T>();
case "Max":
return data.Max<T>();
case "Average":
if (typeof(T) == typeof(int))
{
return (T)Convert.ChangeType((data as List<int>).Average(), typeof(T));
}
if (typeof(T) == typeof(decimal))
{
return (T)Convert.ChangeType((data as List<decimal>).Average(), typeof(T));
}
break;
case "Sum":
if (typeof(T) == typeof(int))
{
return (T)Convert.ChangeType((data as List<int>).Sum(), typeof(T));
}
if (typeof(T) == typeof(decimal))
{
return (T)Convert.ChangeType((data as List<decimal>).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<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
where g.Key != typeof(DynamicNull)
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<int> data = (List<int>)itemsOfDominantTypeOnly.Cast<int>().ToList();
return Aggregate<int>(data, name);
}
else if (dominantType == typeof(decimal))
{
List<decimal> data = (List<decimal>)itemsOfDominantTypeOnly.Cast<decimal>().ToList();
return Aggregate<decimal>(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<DateTime> data = (List<DateTime>)itemsOfDominantTypeOnly.Cast<DateTime>().ToList();
return Aggregate<DateTime>(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<object>)this.Select(predicate, values);
object firstItem = query.FirstOrDefault();
if (firstItem == null)
{
result = new List<object>();
}
else
{
var types = from i in query
group i by i.GetType() into g
where g.Key != typeof(DynamicNull)
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 result;
}
private object ExecuteExtensionMethod(object[] args, string name)
{
object result = null;
var methodTypesToFind = new[]
{
typeof(IEnumerable<DynamicPublishedContent>),
typeof(DynamicPublishedContentList)
};
//find known extension methods that match the first type in the list
MethodInfo toExecute = null;
foreach(var t in methodTypesToFind)
{
toExecute = ExtensionMethodFinder.FindExtensionMethod(t, args, name, false);
if (toExecute != null)
break;
}
if (toExecute != null)
{
if (toExecute.GetParameters().First().ParameterType == typeof(DynamicPublishedContentList))
{
var genericArgs = (new[] { this }).Concat(args);
result = toExecute.Invoke(null, genericArgs.ToArray());
}
else if (TypeHelper.IsTypeAssignableFrom<IQueryable>(toExecute.GetParameters().First().ParameterType))
{
//if it is IQueryable, we'll need to cast Items AsQueryable
var genericArgs = (new[] { Items.AsQueryable() }).Concat(args);
result = toExecute.Invoke(null, genericArgs.ToArray());
}
else
{
var genericArgs = (new[] { Items }).Concat(args);
result = toExecute.Invoke(null, genericArgs.ToArray());
}
}
else
{
throw new MissingMethodException();
}
if (result != null)
{
if (result is IPublishedContent)
{
result = new DynamicPublishedContent((IPublishedContent)result);
}
if (result is IEnumerable<IPublishedContent>)
{
result = new DynamicPublishedContentList((IEnumerable<IPublishedContent>)result);
}
if (result is IEnumerable<DynamicPublishedContent>)
{
result = new DynamicPublishedContentList((IEnumerable<DynamicPublishedContent>)result);
}
}
return result;
}
public IQueryable<T> Where<T>(string predicate, params object[] values)
{
return ((IQueryable<T>)Items.AsQueryable()).Where(predicate, values);
}
public IQueryable<T> OrderBy<T>(string key)
{
return ((IQueryable<T>)Items.AsQueryable()).OrderBy(key);
}
public DynamicGrouping GroupBy<T>(string key)
{
var group = new DynamicGrouping(this, key);
return group;
}
public DynamicGrouping GroupedInto<T>(int groupCount)
{
int groupSize = (int)Math.Ceiling(((decimal)Items.Count() / groupCount));
return new DynamicGrouping(
this
.Items
.Select((node, index) => new KeyValuePair<int, DynamicPublishedContent>(index, node))
.GroupBy(kv => (object)(kv.Key / groupSize))
.Select(item => new Grouping<object, DynamicPublishedContent>()
{
Key = item.Key,
Elements = item.Select(inner => inner.Value)
}));
}
public DynamicGrouping InGroupsOf<T>(int groupSize)
{
return new DynamicGrouping(
this
.Items
.Select((node, index) => new KeyValuePair<int, DynamicPublishedContent>(index, node))
.GroupBy(kv => (object)(kv.Key / groupSize))
.Select(item => new Grouping<object, DynamicPublishedContent>()
{
Key = item.Key,
Elements = item.Select(inner => inner.Value)
}));
}
public IQueryable Select(string predicate, params object[] values)
{
return Items.AsQueryable().Select(predicate, values);
}
public void Add(DynamicPublishedContent publishedContent)
{
publishedContent.OwnerList = this;
this.Items.Add(publishedContent);
}
public void Remove(DynamicPublishedContent publishedContent)
{
if (this.Items.Contains(publishedContent))
{
publishedContent.OwnerList = null;
this.Items.Remove(publishedContent);
}
}
public bool IsNull()
{
return false;
}
public bool HasValue()
{
return true;
}
public IEnumerator<DynamicPublishedContent> GetEnumerator()
{
return Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -2,18 +2,19 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Umbraco.Core.Models;
namespace Umbraco.Core.Dynamics
{
internal static class DynamicPublishedContentListOrdering
{
private static TOut Reduce<TOut>(Func<DynamicPublishedContent, TOut> func, DynamicPublishedContent publishedContent)
private static TOut Reduce<TOut>(Func<DynamicPublishedContentBase, TOut> func, DynamicPublishedContentBase publishedContent)
{
var value = func(publishedContent);
while (value is Func<DynamicPublishedContent, TOut>)
while (value is Func<DynamicPublishedContentBase, TOut>)
{
value = (value as Func<DynamicPublishedContent, TOut>)(publishedContent);
value = (value as Func<DynamicPublishedContentBase, TOut>)(publishedContent);
}
//when you're sorting a list of properties
//and one of those properties doesn't exist, it will come back as DynamicNull
@@ -37,209 +38,209 @@ namespace Umbraco.Core.Dynamics
}
return (TOut)value;
}
public static IOrderedQueryable<DynamicPublishedContent> OrderBy(object source, object key)
internal static IOrderedQueryable<DynamicPublishedContentBase> OrderBy(object source, object key)
{
IEnumerable<DynamicPublishedContent> typedSource = source as IEnumerable<DynamicPublishedContent>;
IEnumerable<DynamicPublishedContentBase> typedSource = source as IEnumerable<DynamicPublishedContentBase>;
LambdaExpression lambda = key as LambdaExpression;
//if the lambda we have returns an actual property, not a dynamic one,
//then the TOut of the func will be the actual type, not object
//Func<DynamicNode, object> func = (Func<DynamicNode, object>)lambda.Compile();
var func = lambda.Compile();
var TOut = func.GetType().GetGenericArguments()[1];
IOrderedQueryable<DynamicPublishedContent> result = null;
if (TOut == typeof(Func<DynamicPublishedContent, object>))
IOrderedQueryable<DynamicPublishedContentBase> result = null;
if (TOut == typeof(Func<DynamicPublishedContentBase, object>))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderBy(x => Reduce<object>(func as Func<DynamicPublishedContent, object>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderBy(x => Reduce<object>(func as Func<DynamicPublishedContentBase, object>, x))
.AsQueryable();
}
if (TOut == typeof(object))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderBy(x => Reduce<object>(func as Func<DynamicPublishedContent, object>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderBy(x => Reduce<object>(func as Func<DynamicPublishedContentBase, object>, x))
.AsQueryable();
}
if (TOut == typeof(bool))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderBy(x => Reduce<bool>(func as Func<DynamicPublishedContent, bool>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderBy(x => Reduce<bool>(func as Func<DynamicPublishedContentBase, bool>, x))
.AsQueryable();
}
if (TOut == typeof(decimal))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderBy(x => Reduce<decimal>(func as Func<DynamicPublishedContent, decimal>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderBy(x => Reduce<decimal>(func as Func<DynamicPublishedContentBase, decimal>, x))
.AsQueryable();
}
if (TOut == typeof(int))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderBy(x => Reduce<int>(func as Func<DynamicPublishedContent, int>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderBy(x => Reduce<int>(func as Func<DynamicPublishedContentBase, int>, x))
.AsQueryable();
}
if (TOut == typeof(string))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderBy(x => Reduce<string>(func as Func<DynamicPublishedContent, string>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderBy(x => Reduce<string>(func as Func<DynamicPublishedContentBase, string>, x))
.AsQueryable();
}
if (TOut == typeof(DateTime))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderBy(x => Reduce<DateTime>(func as Func<DynamicPublishedContent, DateTime>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderBy(x => Reduce<DateTime>(func as Func<DynamicPublishedContentBase, DateTime>, x))
.AsQueryable();
}
return result;
}
public static IOrderedQueryable<DynamicPublishedContent> ThenBy(object source, object key)
internal static IOrderedQueryable<DynamicPublishedContentBase> ThenBy(object source, object key)
{
IOrderedQueryable<DynamicPublishedContent> typedSource = source as IOrderedQueryable<DynamicPublishedContent>;
IOrderedQueryable<DynamicPublishedContentBase> typedSource = source as IOrderedQueryable<DynamicPublishedContentBase>;
LambdaExpression lambda = key as LambdaExpression;
var func = lambda.Compile();
var TOut = func.GetType().GetGenericArguments()[1];
IOrderedQueryable<DynamicPublishedContent> result = null;
if (TOut == typeof(Func<DynamicPublishedContent, object>))
IOrderedQueryable<DynamicPublishedContentBase> result = null;
if (TOut == typeof(Func<DynamicPublishedContentBase, object>))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenBy(x => Reduce<object>(func as Func<DynamicPublishedContent, object>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenBy(x => Reduce<object>(func as Func<DynamicPublishedContentBase, object>, x))
.AsQueryable();
}
if (TOut == typeof(object))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenBy(x => Reduce<object>(func as Func<DynamicPublishedContent, object>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenBy(x => Reduce<object>(func as Func<DynamicPublishedContentBase, object>, x))
.AsQueryable();
}
if (TOut == typeof(bool))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenBy(x => Reduce<bool>(func as Func<DynamicPublishedContent, bool>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenBy(x => Reduce<bool>(func as Func<DynamicPublishedContentBase, bool>, x))
.AsQueryable();
}
if (TOut == typeof(decimal))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenBy(x => Reduce<decimal>(func as Func<DynamicPublishedContent, decimal>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenBy(x => Reduce<decimal>(func as Func<DynamicPublishedContentBase, decimal>, x))
.AsQueryable();
}
if (TOut == typeof(int))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenBy(x => Reduce<int>(func as Func<DynamicPublishedContent, int>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenBy(x => Reduce<int>(func as Func<DynamicPublishedContentBase, int>, x))
.AsQueryable();
}
if (TOut == typeof(string))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenBy(x => Reduce<string>(func as Func<DynamicPublishedContent, string>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenBy(x => Reduce<string>(func as Func<DynamicPublishedContentBase, string>, x))
.AsQueryable();
}
if (TOut == typeof(DateTime))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenBy(x => Reduce<DateTime>(func as Func<DynamicPublishedContent, DateTime>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenBy(x => Reduce<DateTime>(func as Func<DynamicPublishedContentBase, DateTime>, x))
.AsQueryable();
}
return result;
}
public static IOrderedQueryable<DynamicPublishedContent> OrderByDescending(object source, object key)
internal static IOrderedQueryable<DynamicPublishedContentBase> OrderByDescending(object source, object key)
{
IEnumerable<DynamicPublishedContent> typedSource = source as IEnumerable<DynamicPublishedContent>;
IEnumerable<DynamicPublishedContentBase> typedSource = source as IEnumerable<DynamicPublishedContentBase>;
LambdaExpression lambda = key as LambdaExpression;
var func = lambda.Compile();
var TOut = func.GetType().GetGenericArguments()[1];
IOrderedQueryable<DynamicPublishedContent> result = null;
if (TOut == typeof(Func<DynamicPublishedContent, object>))
IOrderedQueryable<DynamicPublishedContentBase> result = null;
if (TOut == typeof(Func<DynamicPublishedContentBase, object>))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderByDescending(x => Reduce<object>(func as Func<DynamicPublishedContent, object>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderByDescending(x => Reduce<object>(func as Func<DynamicPublishedContentBase, object>, x))
.AsQueryable();
}
if (TOut == typeof(object))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderByDescending(x => Reduce<object>(func as Func<DynamicPublishedContent, object>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderByDescending(x => Reduce<object>(func as Func<DynamicPublishedContentBase, object>, x))
.AsQueryable();
}
if (TOut == typeof(bool))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderByDescending(x => Reduce<bool>(func as Func<DynamicPublishedContent, bool>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderByDescending(x => Reduce<bool>(func as Func<DynamicPublishedContentBase, bool>, x))
.AsQueryable();
}
if (TOut == typeof(decimal))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderByDescending(x => Reduce<decimal>(func as Func<DynamicPublishedContent, decimal>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderByDescending(x => Reduce<decimal>(func as Func<DynamicPublishedContentBase, decimal>, x))
.AsQueryable();
}
if (TOut == typeof(int))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderByDescending(x => Reduce<int>(func as Func<DynamicPublishedContent, int>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderByDescending(x => Reduce<int>(func as Func<DynamicPublishedContentBase, int>, x))
.AsQueryable();
}
if (TOut == typeof(string))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderByDescending(x => Reduce<string>(func as Func<DynamicPublishedContent, string>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderByDescending(x => Reduce<string>(func as Func<DynamicPublishedContentBase, string>, x))
.AsQueryable();
}
if (TOut == typeof(DateTime))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.OrderByDescending(x => Reduce<DateTime>(func as Func<DynamicPublishedContent, DateTime>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.OrderByDescending(x => Reduce<DateTime>(func as Func<DynamicPublishedContentBase, DateTime>, x))
.AsQueryable();
}
return result;
}
public static IOrderedQueryable<DynamicPublishedContent> ThenByDescending(object source, object key)
internal static IOrderedQueryable<DynamicPublishedContentBase> ThenByDescending(object source, object key)
{
IOrderedQueryable<DynamicPublishedContent> typedSource = source as IOrderedQueryable<DynamicPublishedContent>;
IOrderedQueryable<DynamicPublishedContentBase> typedSource = source as IOrderedQueryable<DynamicPublishedContentBase>;
LambdaExpression lambda = key as LambdaExpression;
var func = lambda.Compile();
var TOut = func.GetType().GetGenericArguments()[1];
IOrderedQueryable<DynamicPublishedContent> result = null;
if (TOut == typeof(Func<DynamicPublishedContent, object>))
IOrderedQueryable<DynamicPublishedContentBase> result = null;
if (TOut == typeof(Func<DynamicPublishedContentBase, object>))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenByDescending(x => Reduce<object>(func as Func<DynamicPublishedContent, object>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenByDescending(x => Reduce<object>(func as Func<DynamicPublishedContentBase, object>, x))
.AsQueryable();
}
if (TOut == typeof(object))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenByDescending(x => Reduce<object>(func as Func<DynamicPublishedContent, object>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenByDescending(x => Reduce<object>(func as Func<DynamicPublishedContentBase, object>, x))
.AsQueryable();
}
if (TOut == typeof(bool))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenByDescending(x => Reduce<bool>(func as Func<DynamicPublishedContent, bool>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenByDescending(x => Reduce<bool>(func as Func<DynamicPublishedContentBase, bool>, x))
.AsQueryable();
}
if (TOut == typeof(decimal))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenByDescending(x => Reduce<decimal>(func as Func<DynamicPublishedContent, decimal>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenByDescending(x => Reduce<decimal>(func as Func<DynamicPublishedContentBase, decimal>, x))
.AsQueryable();
}
if (TOut == typeof(int))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenByDescending(x => Reduce<int>(func as Func<DynamicPublishedContent, int>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenByDescending(x => Reduce<int>(func as Func<DynamicPublishedContentBase, int>, x))
.AsQueryable();
}
if (TOut == typeof(string))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenByDescending(x => Reduce<string>(func as Func<DynamicPublishedContent, string>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenByDescending(x => Reduce<string>(func as Func<DynamicPublishedContentBase, string>, x))
.AsQueryable();
}
if (TOut == typeof(DateTime))
{
result = (IOrderedQueryable<DynamicPublishedContent>)typedSource
.ThenByDescending(x => Reduce<DateTime>(func as Func<DynamicPublishedContent, DateTime>, x))
result = (IOrderedQueryable<DynamicPublishedContentBase>)typedSource
.ThenByDescending(x => Reduce<DateTime>(func as Func<DynamicPublishedContentBase, DateTime>, x))
.AsQueryable();
}
return result;

View File

@@ -1,263 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Dynamics
{
internal static class DynamicPublishedContentWalker
{
public static DynamicPublishedContent Up(this DynamicPublishedContent context)
{
return context.Up(0);
}
public static DynamicPublishedContent Up(this DynamicPublishedContent context, int number)
{
if (number == 0)
{
return context.Parent;
}
else
{
while ((context = context.Parent) != null && --number >= 0) ;
return context;
}
}
public static DynamicPublishedContent Up(this DynamicPublishedContent context, string nodeTypeAlias)
{
if (string.IsNullOrEmpty(nodeTypeAlias))
{
return context.Parent;
}
else
{
while ((context = context.Parent) != null && context.DocumentTypeAlias != nodeTypeAlias) ;
return context;
}
}
public static DynamicPublishedContent Down(this DynamicPublishedContent context)
{
return context.Down(0);
}
public static DynamicPublishedContent Down(this DynamicPublishedContent context, int number)
{
var children = new DynamicPublishedContentList(context.Children);
if (number == 0)
{
return children.Items.First();
}
else
{
DynamicPublishedContent working = context;
while (number-- >= 0)
{
working = children.Items.First();
children = new DynamicPublishedContentList(working.Children);
}
return working;
}
}
public static DynamicPublishedContent Down(this DynamicPublishedContent context, string nodeTypeAlias)
{
if (string.IsNullOrEmpty(nodeTypeAlias))
{
var children = new DynamicPublishedContentList(context.Children);
return children.Items.First();
}
else
{
return context.Descendants(nodeTypeAlias).Items.FirstOrDefault();
}
}
public static DynamicPublishedContent Next(this DynamicPublishedContent context)
{
return context.Next(0);
}
public static DynamicPublishedContent Next(this DynamicPublishedContent context, int number)
{
if (context.OwnerList == null && context.Parent != null)
{
//var list = context.Parent.Children.Select(n => new DynamicNode(n));
var list = context.Parent.Children;
context.OwnerList = new DynamicPublishedContentList(list);
}
if (context.OwnerList != null)
{
var container = context.OwnerList.Items.ToList();
var currentIndex = container.FindIndex(n => n.Id == context.Id);
if (currentIndex != -1)
{
return container.ElementAtOrDefault(currentIndex + (number + 1));
}
else
{
throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", context.Id));
}
}
else
{
throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", context.Id));
}
}
public static DynamicPublishedContent Sibling(this DynamicPublishedContent context, int number)
{
if (context.OwnerList == null && context.Parent != null)
{
//var list = context.Parent.Children.Select(n => new DynamicNode(n));
var list = context.Parent.Children;
context.OwnerList = new DynamicPublishedContentList(list);
}
if (context.OwnerList != null)
{
var container = context.OwnerList.Items.ToList();
var currentIndex = container.FindIndex(n => n.Id == context.Id);
if (currentIndex != -1)
{
return container.ElementAtOrDefault(currentIndex + number);
}
else
{
throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", context.Id));
}
}
else
{
throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", context.Id));
}
}
public static DynamicPublishedContent Sibling(this DynamicPublishedContent context, string nodeTypeAlias)
{
if (context.OwnerList == null && context.Parent != null)
{
//var list = context.Parent.Children.Select(n => new DynamicNode(n));
var list = context.Parent.Children;
context.OwnerList = new DynamicPublishedContentList(list);
}
if (context.OwnerList != null)
{
var container = context.OwnerList.Items.ToList();
var currentIndex = container.FindIndex(n => n.Id == context.Id);
if (currentIndex != -1)
{
var workingIndex = currentIndex + 1;
while (workingIndex != currentIndex)
{
var working = container.ElementAtOrDefault(workingIndex);
if (working != null && working.DocumentTypeAlias == nodeTypeAlias)
{
return working;
}
workingIndex++;
if (workingIndex > container.Count)
{
workingIndex = 0;
}
}
return null;
}
else
{
throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", context.Id));
}
}
else
{
throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", context.Id));
}
}
public static DynamicPublishedContent Next(this DynamicPublishedContent context, string nodeTypeAlias)
{
if (context.OwnerList == null && context.Parent != null)
{
//var list = context.Parent.Children.Select(n => new DynamicNode(n));
var list = context.Parent.Children;
context.OwnerList = new DynamicPublishedContentList(list);
}
if (context.OwnerList != null)
{
var container = context.OwnerList.Items.ToList();
var currentIndex = container.FindIndex(n => n.Id == context.Id);
if (currentIndex != -1)
{
var newIndex = container.FindIndex(currentIndex, n => n.DocumentTypeAlias == nodeTypeAlias);
if (newIndex != -1)
{
return container.ElementAt(newIndex);
}
return null;
}
else
{
throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", context.Id));
}
}
else
{
throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", context.Id));
}
}
public static DynamicPublishedContent Previous(this DynamicPublishedContent context)
{
return context.Previous(0);
}
public static DynamicPublishedContent Previous(this DynamicPublishedContent context, int number)
{
if (context.OwnerList == null && context.Parent != null)
{
//var list = context.Parent.Children.Select(n => new DynamicNode(n));
var list = context.Parent.Children;
context.OwnerList = new DynamicPublishedContentList(list);
}
if (context.OwnerList != null)
{
List<DynamicPublishedContent> container = context.OwnerList.Items.ToList();
int currentIndex = container.FindIndex(n => n.Id == context.Id);
if (currentIndex != -1)
{
return container.ElementAtOrDefault(currentIndex + (number - 1));
}
else
{
throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", context.Id));
}
}
else
{
throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", context.Id));
}
}
public static DynamicPublishedContent Previous(this DynamicPublishedContent context, string nodeTypeAlias)
{
if (context.OwnerList == null && context.Parent != null)
{
//var list = context.Parent.Children.Select(n => new DynamicNode(n));
var list = context.Parent.Children;
context.OwnerList = new DynamicPublishedContentList(list);
}
if (context.OwnerList != null)
{
List<DynamicPublishedContent> container = context.OwnerList.Items.ToList();
int currentIndex = container.FindIndex(n => n.Id == context.Id);
if (currentIndex != -1)
{
var previousNodes = container.Take(currentIndex).ToList();
int newIndex = previousNodes.FindIndex(n => n.DocumentTypeAlias == nodeTypeAlias);
if (newIndex != -1)
{
return container.ElementAt(newIndex);
}
return null;
}
else
{
throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", context.Id));
}
}
else
{
throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", context.Id));
}
}
}
}

View File

@@ -6,6 +6,7 @@ using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Diagnostics;
using Umbraco.Core.Models;
namespace Umbraco.Core.Dynamics
{
@@ -21,22 +22,22 @@ namespace Umbraco.Core.Dynamics
if (source == null) throw new ArgumentNullException("source");
if (predicate == null) throw new ArgumentNullException("predicate");
LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, true, values);
if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicPublishedContent))
if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicPublishedContentBase))
{
//source list is DynamicNode and the lambda returns a Func<object>
IQueryable<DynamicPublishedContent> typedSource = source as IQueryable<DynamicPublishedContent>;
IQueryable<DynamicPublishedContentBase> typedSource = source as IQueryable<DynamicPublishedContentBase>;
var compiledFunc = lambda.Compile();
Func<DynamicPublishedContent, object> func = null;
Func<DynamicPublishedContent, bool> boolFunc = null;
if (compiledFunc is Func<DynamicPublishedContent, object>)
Func<DynamicPublishedContentBase, object> func = null;
Func<DynamicPublishedContentBase, bool> boolFunc = null;
if (compiledFunc is Func<DynamicPublishedContentBase, object>)
{
func = (Func<DynamicPublishedContent, object>)compiledFunc;
func = (Func<DynamicPublishedContentBase, object>)compiledFunc;
}
if (compiledFunc is Func<DynamicPublishedContent, bool>)
if (compiledFunc is Func<DynamicPublishedContentBase, bool>)
{
boolFunc = (Func<DynamicPublishedContent, bool>)compiledFunc;
boolFunc = (Func<DynamicPublishedContentBase, bool>)compiledFunc;
}
return typedSource.Where(delegate(DynamicPublishedContent node)
return typedSource.Where(delegate(DynamicPublishedContentBase node)
{
object value = -1;
//value = func(node);
@@ -46,13 +47,13 @@ namespace Umbraco.Core.Dynamics
if (func != null)
{
var firstFuncResult = func(node);
if (firstFuncResult is Func<DynamicPublishedContent, object>)
if (firstFuncResult is Func<DynamicPublishedContentBase, object>)
{
value = (firstFuncResult as Func<DynamicPublishedContent, object>)(node);
value = (firstFuncResult as Func<DynamicPublishedContentBase, object>)(node);
}
if (firstFuncResult is Func<DynamicPublishedContent, bool>)
if (firstFuncResult is Func<DynamicPublishedContentBase, bool>)
{
value = (firstFuncResult as Func<DynamicPublishedContent, bool>)(node);
value = (firstFuncResult as Func<DynamicPublishedContentBase, bool>)(node);
}
if (firstFuncResult is bool)
{
@@ -86,28 +87,28 @@ namespace Umbraco.Core.Dynamics
}
}
public static IQueryable Select(this IQueryable<DynamicPublishedContent> source, string selector, params object[] values)
public static IQueryable Select(this IQueryable<DynamicPublishedContentBase> 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, typeof(object), selector, false, values);
if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicPublishedContent))
if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicPublishedContentBase))
{
//source list is DynamicNode and the lambda returns a Func<object>
IQueryable<DynamicPublishedContent> typedSource = source as IQueryable<DynamicPublishedContent>;
IQueryable<DynamicPublishedContentBase> typedSource = source as IQueryable<DynamicPublishedContentBase>;
var compiledFunc = lambda.Compile();
Func<DynamicPublishedContent, object> func = null;
if (compiledFunc is Func<DynamicPublishedContent, object>)
Func<DynamicPublishedContentBase, object> func = null;
if (compiledFunc is Func<DynamicPublishedContentBase, object>)
{
func = (Func<DynamicPublishedContent, object>)compiledFunc;
func = (Func<DynamicPublishedContentBase, object>)compiledFunc;
}
return typedSource.Select(delegate(DynamicPublishedContent node)
return typedSource.Select(delegate(DynamicPublishedContentBase node)
{
object value = null;
value = func(node);
if (value is Func<DynamicPublishedContent, object>)
if (value is Func<DynamicPublishedContentBase, object>)
{
var innerValue = (value as Func<DynamicPublishedContent, object>)(node);
var innerValue = (value as Func<DynamicPublishedContentBase, object>)(node);
return innerValue;
}
return value;
@@ -133,7 +134,7 @@ namespace Umbraco.Core.Dynamics
if (source == null) throw new ArgumentNullException("source");
if (ordering == null) throw new ArgumentNullException("ordering");
IQueryable<DynamicPublishedContent> typedSource = source as IQueryable<DynamicPublishedContent>;
IQueryable<DynamicPublishedContentBase> typedSource = source as IQueryable<DynamicPublishedContentBase>;
if (!ordering.Contains(","))
{
bool descending = false;
@@ -149,10 +150,10 @@ namespace Umbraco.Core.Dynamics
}
LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(object), ordering, false, values);
if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicPublishedContent))
if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicPublishedContentBase))
{
//source list is DynamicNode and the lambda returns a Func<object>
Func<DynamicPublishedContent, object> func = (Func<DynamicPublishedContent, object>)lambda.Compile();
Func<DynamicPublishedContentBase, object> func = (Func<DynamicPublishedContentBase, object>)lambda.Compile();
//get the values out
var query = typedSource.ToList().ConvertAll(item => new { node = item, key = EvaluateDynamicNodeFunc(item, func) });
if (query.Count == 0)
@@ -246,13 +247,13 @@ namespace Umbraco.Core.Dynamics
return null;
}
}
private static object EvaluateDynamicNodeFunc(DynamicPublishedContent publishedContent, Func<DynamicPublishedContent, object> func)
private static object EvaluateDynamicNodeFunc(DynamicPublishedContentBase publishedContent, Func<DynamicPublishedContentBase, object> func)
{
object value = -1;
var firstFuncResult = func(publishedContent);
if (firstFuncResult is Func<DynamicPublishedContent, object>)
if (firstFuncResult is Func<DynamicPublishedContentBase, object>)
{
value = (firstFuncResult as Func<DynamicPublishedContent, object>)(publishedContent);
value = (firstFuncResult as Func<DynamicPublishedContentBase, object>)(publishedContent);
}
if (firstFuncResult.GetType().IsValueType || firstFuncResult is string)
{

View File

@@ -4,6 +4,7 @@ using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Umbraco.Core.Models;
namespace Umbraco.Core.Dynamics
{
@@ -507,7 +508,7 @@ namespace Umbraco.Core.Dynamics
(expr as LambdaExpression).Parameters.CopyTo(parameters, 0);
var invokedExpr = Expression.Invoke(expr, parameters);
var not = Expression.Not(Expression.TypeAs(invokedExpr, typeof(Nullable<bool>)));
expr = Expression.Lambda<Func<DynamicPublishedContent, bool>>(
expr = Expression.Lambda<Func<DynamicPublishedContentBase, bool>>(
Expression.Condition(
Expression.Property(not, "HasValue"),
Expression.Property(not, "Value"),
@@ -854,11 +855,11 @@ namespace Umbraco.Core.Dynamics
Expression[] args = ParseArgumentList();
MethodBase mb;
LambdaExpression instanceAsString = null;
ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicPublishedContent), "instance");
ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicPublishedContentBase), "instance");
if (type.IsGenericType && type != typeof(string))
{
var typeArgs = type.GetGenericArguments();
if (typeArgs[0] == typeof(DynamicPublishedContent))
if (typeArgs[0] == typeof(DynamicPublishedContentBase))
{
if (instance != null && instance is LambdaExpression)
{
@@ -929,14 +930,14 @@ namespace Umbraco.Core.Dynamics
//this will invoke TryGetMember (but wrapped in an expression tree)
//so that when it's evaluated, DynamicNode should be supported
ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicPublishedContent), "instance");
ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicPublishedContentBase), "instance");
ParameterExpression convertDynamicNullToBooleanFalse = Expression.Parameter(typeof(bool), "convertDynamicNullToBooleanFalse");
ParameterExpression result = Expression.Parameter(typeof(object), "result");
ParameterExpression binder = Expression.Variable(typeof(DynamicQueryableGetMemberBinder), "binder");
ParameterExpression ignoreCase = Expression.Variable(typeof(bool), "ignoreCase");
ConstructorInfo getMemberBinderConstructor = typeof(DynamicQueryableGetMemberBinder).GetConstructor(new Type[] { typeof(string), typeof(bool) });
LabelTarget blockReturnLabel = Expression.Label(typeof(object));
MethodInfo method = typeof(DynamicPublishedContent).GetMethod("TryGetMember");
MethodInfo method = typeof(DynamicPublishedContentBase).GetMethod("TryGetMember");
BlockExpression block = Expression.Block(
typeof(object),
@@ -957,10 +958,10 @@ namespace Umbraco.Core.Dynamics
Expression.Return(blockReturnLabel, result),
Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object)))
);
LambdaExpression lax = Expression.Lambda<Func<DynamicPublishedContent, object>>(block, instanceExpression);
LambdaExpression lax = Expression.Lambda<Func<DynamicPublishedContentBase, object>>(block, instanceExpression);
return lax;
}
if (typeof(Func<DynamicPublishedContent, object>).IsAssignableFrom(type))
if (typeof(Func<DynamicPublishedContentBase, object>).IsAssignableFrom(type))
{
//accessing a property off an already resolved DynamicNode TryGetMember call
//e.g. uBlogsyPostDate.Date
@@ -971,8 +972,8 @@ namespace Umbraco.Core.Dynamics
ParameterExpression result = Expression.Parameter(typeof(object), "result");
ParameterExpression idParam = Expression.Parameter(typeof(string), "id");
ParameterExpression lambdaResult = Expression.Parameter(typeof(object), "lambdaResult");
ParameterExpression lambdaInstanceExpression = Expression.Parameter(typeof(DynamicPublishedContent), "lambdaInstanceExpression");
ParameterExpression instanceExpression = Expression.Parameter(typeof(Func<DynamicPublishedContent, object>), "instance");
ParameterExpression lambdaInstanceExpression = Expression.Parameter(typeof(DynamicPublishedContentBase), "lambdaInstanceExpression");
ParameterExpression instanceExpression = Expression.Parameter(typeof(Func<DynamicPublishedContentBase, object>), "instance");
LabelTarget blockReturnLabel = Expression.Label(typeof(object));
BlockExpression block = Expression.Block(
@@ -991,7 +992,7 @@ namespace Umbraco.Core.Dynamics
Expression.Return(blockReturnLabel, result),
Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object)))
);
LambdaExpression lax = Expression.Lambda<Func<DynamicPublishedContent, object>>(block, lambdaInstanceExpression);
LambdaExpression lax = Expression.Lambda<Func<DynamicPublishedContentBase, object>>(block, lambdaInstanceExpression);
return lax;
}
}
@@ -1050,11 +1051,11 @@ namespace Umbraco.Core.Dynamics
switch (methodReturnType.Name)
{
case "String":
return Expression.Lambda<Func<DynamicPublishedContent, string>>(block, instanceExpression);
return Expression.Lambda<Func<DynamicPublishedContentBase, string>>(block, instanceExpression);
case "Int32":
return Expression.Lambda<Func<DynamicPublishedContent, int>>(block, instanceExpression);
return Expression.Lambda<Func<DynamicPublishedContentBase, int>>(block, instanceExpression);
case "Boolean":
return Expression.Lambda<Func<DynamicPublishedContent, bool>>(block, instanceExpression);
return Expression.Lambda<Func<DynamicPublishedContentBase, bool>>(block, instanceExpression);
}
return Expression.Call(instance, (MethodInfo)method, args);
}
@@ -1092,8 +1093,8 @@ namespace Umbraco.Core.Dynamics
Expression.Return(cblockReturnLabel, cresult),
Expression.Label(cblockReturnLabel, Expression.Constant(null, typeof(string))));
LambdaExpression lax2 = Expression.Lambda<Func<DynamicPublishedContent, string>>(cblock, instanceExpression);
var expression = Expression.Lambda<Func<DynamicPublishedContent, string>>(cblock, instanceExpression);
LambdaExpression lax2 = Expression.Lambda<Func<DynamicPublishedContentBase, string>>(cblock, instanceExpression);
var expression = Expression.Lambda<Func<DynamicPublishedContentBase, string>>(cblock, instanceExpression);
return expression;
}
@@ -1410,7 +1411,7 @@ namespace Umbraco.Core.Dynamics
//if the type of the expression is a func<DynamicNode, object> - invokable returning object,
//we are going to return it here, because we can get the real value when we actually have the instance
//if (typeof(Func<DynamicNode, object>).IsAssignableFrom(expr.Type)) return expr;
if (expr is LambdaExpression && ((LambdaExpression)expr).Parameters.Count > 0 && ((LambdaExpression)expr).Parameters[0].Type == typeof(DynamicPublishedContent))
if (expr is LambdaExpression && ((LambdaExpression)expr).Parameters.Count > 0 && ((LambdaExpression)expr).Parameters[0].Type == typeof(DynamicPublishedContentBase))
{
return expr;
}
@@ -1689,12 +1690,12 @@ namespace Umbraco.Core.Dynamics
UnaryExpression unboxedLeft = null, unboxedRight = null;
ParameterExpression[] parameters = null;
if (left is LambdaExpression && (left as LambdaExpression).Type.GetGenericArguments().First() == typeof(DynamicPublishedContent))
if (left is LambdaExpression && (left as LambdaExpression).Type.GetGenericArguments().First() == typeof(DynamicPublishedContentBase))
{
leftIsLambda = true;
}
if (right is LambdaExpression && (right as LambdaExpression).Type.GetGenericArguments().First() == typeof(DynamicPublishedContent))
if (right is LambdaExpression && (right as LambdaExpression).Type.GetGenericArguments().First() == typeof(DynamicPublishedContentBase))
{
rightIsLambda = true;
}
@@ -1748,11 +1749,11 @@ namespace Umbraco.Core.Dynamics
if (expressionType == ExpressionType.AndAlso)
{
return ExpressionExtensions.And<DynamicPublishedContent>(left as Expression<Func<DynamicPublishedContent, bool>>, right as Expression<Func<DynamicPublishedContent, bool>>);
return ExpressionExtensions.And<DynamicPublishedContentBase>(left as Expression<Func<DynamicPublishedContentBase, bool>>, right as Expression<Func<DynamicPublishedContentBase, bool>>);
}
if (expressionType == ExpressionType.OrElse)
{
return ExpressionExtensions.Or<DynamicPublishedContent>(left as Expression<Func<DynamicPublishedContent, bool>>, right as Expression<Func<DynamicPublishedContent, bool>>);
return ExpressionExtensions.Or<DynamicPublishedContentBase>(left as Expression<Func<DynamicPublishedContentBase, bool>>, right as Expression<Func<DynamicPublishedContentBase, bool>>);
}
}
@@ -1783,11 +1784,11 @@ namespace Umbraco.Core.Dynamics
//left is invoked and unboxed to right's TOut, right was not boxed
if (expressionType == ExpressionType.AndAlso)
{
return ExpressionExtensions.And<DynamicPublishedContent>(right as Expression<Func<DynamicPublishedContent, bool>>, Expression.Lambda<Func<DynamicPublishedContent, bool>>(unboxedLeft, parameters) as Expression<Func<DynamicPublishedContent, bool>>);
return ExpressionExtensions.And<DynamicPublishedContentBase>(right as Expression<Func<DynamicPublishedContentBase, bool>>, Expression.Lambda<Func<DynamicPublishedContentBase, bool>>(unboxedLeft, parameters) as Expression<Func<DynamicPublishedContentBase, bool>>);
}
if (expressionType == ExpressionType.OrElse)
{
return ExpressionExtensions.And<DynamicPublishedContent>(right as Expression<Func<DynamicPublishedContent, bool>>, Expression.Lambda<Func<DynamicPublishedContent, bool>>(unboxedLeft, parameters) as Expression<Func<DynamicPublishedContent, bool>>);
return ExpressionExtensions.And<DynamicPublishedContentBase>(right as Expression<Func<DynamicPublishedContentBase, bool>>, Expression.Lambda<Func<DynamicPublishedContentBase, bool>>(unboxedLeft, parameters) as Expression<Func<DynamicPublishedContentBase, bool>>);
}
}
else
@@ -1804,11 +1805,11 @@ namespace Umbraco.Core.Dynamics
//right is invoked and unboxed to left's TOut, left was not boxed
if (expressionType == ExpressionType.AndAlso)
{
return ExpressionExtensions.And<DynamicPublishedContent>(left as Expression<Func<DynamicPublishedContent, bool>>, Expression.Lambda<Func<DynamicPublishedContent, bool>>(unboxedRight, parameters) as Expression<Func<DynamicPublishedContent, bool>>);
return ExpressionExtensions.And<DynamicPublishedContentBase>(left as Expression<Func<DynamicPublishedContentBase, bool>>, Expression.Lambda<Func<DynamicPublishedContentBase, bool>>(unboxedRight, parameters) as Expression<Func<DynamicPublishedContentBase, bool>>);
}
if (expressionType == ExpressionType.OrElse)
{
return ExpressionExtensions.And<DynamicPublishedContent>(left as Expression<Func<DynamicPublishedContent, bool>>, Expression.Lambda<Func<DynamicPublishedContent, bool>>(unboxedRight, parameters) as Expression<Func<DynamicPublishedContent, bool>>);
return ExpressionExtensions.And<DynamicPublishedContentBase>(left as Expression<Func<DynamicPublishedContentBase, bool>>, Expression.Lambda<Func<DynamicPublishedContentBase, bool>>(unboxedRight, parameters) as Expression<Func<DynamicPublishedContentBase, bool>>);
}
}
@@ -1879,7 +1880,7 @@ namespace Umbraco.Core.Dynamics
break;
case ExpressionType.Modulo:
binaryExpression = Expression.Modulo(finalLeft, finalRight);
return (Expression.Lambda<Func<DynamicPublishedContent, int>>(binaryExpression, parameters));
return (Expression.Lambda<Func<DynamicPublishedContentBase, int>>(binaryExpression, parameters));
case ExpressionType.AndAlso:
if ((leftIsLambda && rightIsLambda && sequenceEqual) || (!leftIsLambda && !rightIsLambda))
{
@@ -1887,7 +1888,7 @@ namespace Umbraco.Core.Dynamics
}
else
{
return (Expression.Lambda<Func<DynamicPublishedContent, Boolean>>(Expression.AndAlso(finalLeft, finalRight), parameters));
return (Expression.Lambda<Func<DynamicPublishedContentBase, Boolean>>(Expression.AndAlso(finalLeft, finalRight), parameters));
}
case ExpressionType.OrElse:
if (leftIsLambda && rightIsLambda && sequenceEqual || (!leftIsLambda && !rightIsLambda))
@@ -1896,7 +1897,7 @@ namespace Umbraco.Core.Dynamics
}
else
{
return (Expression.Lambda<Func<DynamicPublishedContent, Boolean>>(Expression.OrElse(finalLeft, finalRight), parameters));
return (Expression.Lambda<Func<DynamicPublishedContentBase, Boolean>>(Expression.OrElse(finalLeft, finalRight), parameters));
}
default:
return Expression.Equal(left, right);
@@ -1904,7 +1905,7 @@ namespace Umbraco.Core.Dynamics
if (leftIsLambda || rightIsLambda)
{
var body = Expression.Condition(Expression.TypeEqual(innerLeft, right.Type), binaryExpression, Expression.Constant(false));
return Expression.Lambda<Func<DynamicPublishedContent, bool>>(body, parameters);
return Expression.Lambda<Func<DynamicPublishedContentBase, bool>>(body, parameters);
}
else
{

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models;
namespace Umbraco.Core.Dynamics
{
@@ -47,7 +48,7 @@ namespace Umbraco.Core.Dynamics
return new DynamicPublishedContentList(all.Items.OrderBy(x => Guid.NewGuid()).Take(max));
}
public static DynamicPublishedContent Random(this DynamicPublishedContentList all)
public static DynamicPublishedContentBase Random(this DynamicPublishedContentList all)
{
return all.Items.OrderBy(x => Guid.NewGuid()).First();
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Collections;
using System.Dynamic;
using Umbraco.Core.Models;
namespace Umbraco.Core.Dynamics
{
@@ -13,7 +14,7 @@ namespace Umbraco.Core.Dynamics
public IEnumerator<T> GetEnumerator()
{
var temp = new DynamicPublishedContentList(Elements.Cast<DynamicPublishedContent>());
var temp = new DynamicPublishedContentList(Elements.Cast<DynamicPublishedContentBase>());
return (IEnumerator<T>)temp.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
@@ -42,7 +43,7 @@ namespace Umbraco.Core.Dynamics
object key = null;
(item as DynamicObject).TryGetMember(new DynamicQueryableGetMemberBinder(ordering, false), out key);
return key;
}).Cast<DynamicPublishedContent>());
}).Cast<DynamicPublishedContentBase>());
}
else
{
@@ -51,7 +52,7 @@ namespace Umbraco.Core.Dynamics
object key = null;
(item as DynamicObject).TryGetMember(new DynamicQueryableGetMemberBinder(ordering, false), out key);
return key;
}).Cast<DynamicPublishedContent>());
}).Cast<DynamicPublishedContentBase>());
}
}
}

View File

@@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Dynamics
{
/// <summary>
/// This exists only because we want Dynamics in the Core project but DynamicNode has references to ContentType to run some queries
/// and currently the business logic part of Umbraco is still in the legacy project and we don't want to move that to the core so in the
/// meantime until the new APIs are made, we need to have this data source in place with a resolver which is set in the web project.
/// </summary>
internal interface IDynamicPublishedContentDataSource
{
Guid GetDataType(string docTypeAlias, string propertyAlias);
}
}