Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 3
0
 internal DynamicPublishedContent(IPublishedContent content, DynamicPublishedContentList contentList)
 {
     PublishedContent = content;
     _contentList     = contentList;
 }
Ejemplo n.º 4
0
        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);
        }