public bool Where(string predicate) { //Totally gonna cheat here var dynamicDocumentList = new DynamicPublishedContentList(); dynamicDocumentList.Add(this); var filtered = dynamicDocumentList.Where <DynamicPublishedContent>(predicate); if (Queryable.Count(filtered) == 1) { //this node matches the predicate return(true); } return(false); }
/// <summary> /// Attempts to call a method on the dynamic object /// </summary> /// <param name="binder"></param> /// <param name="args"></param> /// <param name="result"></param> /// <returns></returns> public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { var runtimeCache = ApplicationContext.Current != null ? ApplicationContext.Current.ApplicationCache.RuntimeCache : new NullCacheProvider(); var attempt = DynamicInstanceHelper.TryInvokeMember(runtimeCache, this, binder, args, new[] { typeof(DynamicPublishedContent) }); if (attempt.Success) { result = attempt.Result.ObjectResult; //need to check the return type and possibly cast if result is from an extension method found if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod) { //we don't need to cast if it is already DynamicPublishedContent if (attempt.Result.ObjectResult != null && (!(attempt.Result.ObjectResult is DynamicPublishedContent))) { if (attempt.Result.ObjectResult is IPublishedContent) { result = new DynamicPublishedContent((IPublishedContent)attempt.Result.ObjectResult); } else if (attempt.Result.ObjectResult is IEnumerable <DynamicPublishedContent> ) { result = new DynamicPublishedContentList((IEnumerable <DynamicPublishedContent>)attempt.Result.ObjectResult); } else if (attempt.Result.ObjectResult is IEnumerable <IPublishedContent> ) { result = new DynamicPublishedContentList((IEnumerable <IPublishedContent>)attempt.Result.ObjectResult); } } } return(true); } //this is the result of an extension method execution gone wrong so we return dynamic null if (attempt.Result != null && attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod && attempt.Exception is TargetInvocationException) { result = DynamicNull.Null; return(true); } result = null; return(false); }
internal DynamicPublishedContent(IPublishedContent content, DynamicPublishedContentList contentList) { PublishedContent = content; _contentList = contentList; }
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { //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 firstArg = args.FirstOrDefault(); //this is to check for 'DocumentTypeAlias' vs 'NodeTypeAlias' for compatibility if (firstArg != null && firstArg.ToString().InvariantStartsWith("NodeTypeAlias")) { firstArg = "DocumentTypeAlias" + firstArg.ToString().Substring("NodeTypeAlias".Length); } var name = binder.Name; if (name == "Single") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] {} : args.Skip(1).ToArray(); var single = Single <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(single); return(true); } if (name == "SingleOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var single = SingleOrDefault <DynamicPublishedContent>(predicate, values); if (single == null) { result = DynamicNull.Null; } else { result = new DynamicPublishedContent(single); } return(true); } if (name == "First") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var first = First <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(first); return(true); } if (name == "FirstOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var first = FirstOrDefault <DynamicPublishedContent>(predicate, values); if (first == null) { result = DynamicNull.Null; } else { result = new DynamicPublishedContent(first); } return(true); } if (name == "Last") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var last = Last <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(last); return(true); } if (name == "LastOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var last = LastOrDefault <DynamicPublishedContent>(predicate, values); if (last == null) { result = DynamicNull.Null; } else { result = new DynamicPublishedContent(last); } return(true); } if (name == "Where") { string predicate = firstArg.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(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(OrderBy <DynamicPublishedContent>(firstArg.ToString()).ToList()); return(true); } if (name == "Take") { result = new DynamicPublishedContentList(this.Take <DynamicPublishedContent>((int)firstArg)); return(true); } if (name == "Skip") { result = new DynamicPublishedContentList(this.Skip <DynamicPublishedContent>((int)firstArg)); return(true); } if (name == "InGroupsOf") { int groupSize; if (int.TryParse(firstArg.ToString(), out groupSize)) { result = InGroupsOf(groupSize); return(true); } result = DynamicNull.Null; return(true); } if (name == "GroupedInto") { int groupCount; if (int.TryParse(firstArg.ToString(), out groupCount)) { result = GroupedInto(groupCount); return(true); } result = DynamicNull.Null; return(true); } if (name == "GroupBy") { result = GroupBy(firstArg.ToString()); return(true); } if (name == "Average" || name == "Min" || name == "Max" || name == "Sum") { result = Aggregate(args, name); return(true); } if (name == "Union") { // check DynamicPublishedContentList before IEnumerable<...> because DynamicPublishedContentList // is IEnumerable<...> so ... the check on DynamicPublishedContentList would never be reached. var firstArgAsDynamicPublishedContentList = firstArg as DynamicPublishedContentList; if (firstArgAsDynamicPublishedContentList != null) { result = new DynamicPublishedContentList(Items.Union((firstArgAsDynamicPublishedContentList).Items)); return(true); } var firstArgAsIEnumerable = firstArg as IEnumerable <DynamicPublishedContent>; if (firstArgAsIEnumerable != null) { result = new DynamicPublishedContentList(Items.Union(firstArgAsIEnumerable)); return(true); } } if (name == "Except") { if ((firstArg as IEnumerable <DynamicPublishedContent>) != null) { result = new DynamicPublishedContentList(Items.Except(firstArg as IEnumerable <DynamicPublishedContent>, new DynamicPublishedContentIdEqualityComparer())); return(true); } } if (name == "Intersect") { if ((firstArg as IEnumerable <DynamicPublishedContent>) != null) { result = new DynamicPublishedContentList(Items.Intersect(firstArg as IEnumerable <DynamicPublishedContent>, new DynamicPublishedContentIdEqualityComparer())); return(true); } } if (name == "Distinct") { result = new DynamicPublishedContentList(Items.Distinct(new DynamicPublishedContentIdEqualityComparer())); return(true); } if (name == "Pluck" || name == "Select") { result = Pluck(args); return(true); } //ok, now lets try to match by member, property, extensino method var attempt = DynamicInstanceHelper.TryInvokeMember(this, binder, args, new[] { typeof(IEnumerable <DynamicPublishedContent>), typeof(DynamicPublishedContentList) }); if (attempt.Success) { result = attempt.Result.ObjectResult; //need to check the return type and possibly cast if result is from an extension method found if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod) { //we don't need to cast if the result is already DynamicPublishedContentList if (attempt.Result.ObjectResult != null && (!(attempt.Result.ObjectResult is DynamicPublishedContentList))) { if (attempt.Result.ObjectResult is IPublishedContent) { result = new DynamicPublishedContent((IPublishedContent)attempt.Result.ObjectResult); } else if (attempt.Result.ObjectResult is IEnumerable <DynamicPublishedContent> ) { result = new DynamicPublishedContentList((IEnumerable <DynamicPublishedContent>)attempt.Result.ObjectResult); } else if (attempt.Result.ObjectResult is IEnumerable <IPublishedContent> ) { result = new DynamicPublishedContentList((IEnumerable <IPublishedContent>)attempt.Result.ObjectResult); } } } return(true); } //this is the result of an extension method execution gone wrong so we return dynamic null if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod && attempt.Exception != null && attempt.Exception is TargetInvocationException) { result = DynamicNull.Null; return(true); } result = null; return(false); }
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 firstArg = args.FirstOrDefault(); //this is to check for 'DocumentTypeAlias' vs 'NodeTypeAlias' for compatibility if (firstArg != null && firstArg.ToString().InvariantStartsWith("NodeTypeAlias")) { firstArg = "DocumentTypeAlias" + firstArg.ToString().Substring("NodeTypeAlias".Length); } var name = binder.Name; if (name == "Single") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] {} : args.Skip(1).ToArray(); var single = this.Single <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(single); return(true); } if (name == "SingleOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var single = this.SingleOrDefault <DynamicPublishedContent>(predicate, values); if (single == null) { result = new DynamicNull(); } else { result = new DynamicPublishedContent(single); } return(true); } if (name == "First") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var first = this.First <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(first); return(true); } if (name == "FirstOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var first = this.FirstOrDefault <DynamicPublishedContent>(predicate, values); if (first == null) { result = new DynamicNull(); } else { result = new DynamicPublishedContent(first); } return(true); } if (name == "Last") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var last = this.Last <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(last); return(true); } if (name == "LastOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var last = this.LastOrDefault <DynamicPublishedContent>(predicate, values); if (last == null) { result = new DynamicNull(); } else { result = new DynamicPublishedContent(last); } return(true); } if (name == "Where") { string predicate = firstArg.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>(firstArg.ToString()).ToList()); return(true); } if (name == "Take") { result = new DynamicPublishedContentList(this.Take((int)firstArg)); return(true); } if (name == "Skip") { result = new DynamicPublishedContentList(this.Skip((int)firstArg)); return(true); } if (name == "InGroupsOf") { int groupSize = 0; if (int.TryParse(firstArg.ToString(), out groupSize)) { result = InGroupsOf(groupSize); return(true); } result = new DynamicNull(); return(true); } if (name == "GroupedInto") { int groupCount = 0; if (int.TryParse(firstArg.ToString(), out groupCount)) { result = GroupedInto(groupCount); return(true); } result = new DynamicNull(); return(true); } if (name == "GroupBy") { result = GroupBy(firstArg.ToString()); return(true); } if (name == "Average" || name == "Min" || name == "Max" || name == "Sum") { result = Aggregate(args, name); return(true); } if (name == "Union") { if ((firstArg as IEnumerable <DynamicPublishedContent>) != null) { result = new DynamicPublishedContentList(this.Items.Union(firstArg as IEnumerable <DynamicPublishedContent>)); return(true); } if ((firstArg as DynamicPublishedContentList) != null) { result = new DynamicPublishedContentList(this.Items.Union((firstArg as DynamicPublishedContentList).Items)); return(true); } } if (name == "Except") { if ((firstArg as IEnumerable <DynamicPublishedContent>) != null) { result = new DynamicPublishedContentList(this.Items.Except(firstArg as IEnumerable <DynamicPublishedContent>, new DynamicPublishedContentIdEqualityComparer())); return(true); } if ((firstArg as DynamicPublishedContentList) != null) { result = new DynamicPublishedContentList(this.Items.Except((firstArg as DynamicPublishedContentList).Items, new DynamicPublishedContentIdEqualityComparer())); return(true); } } if (name == "Intersect") { if ((firstArg as IEnumerable <DynamicPublishedContent>) != null) { result = new DynamicPublishedContentList(this.Items.Intersect(firstArg as IEnumerable <DynamicPublishedContent>, new DynamicPublishedContentIdEqualityComparer())); return(true); } if ((firstArg as DynamicPublishedContentList) != null) { result = new DynamicPublishedContentList(this.Items.Intersect((firstArg 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 DynamicNull; result = new DynamicNull(); return(true); } catch { result = null; return(false); } } } catch { result = null; return(false); } }
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); }