Beispiel #1
0
        /// <summary>
        ///     Will walk the path by using the path seperator "." and evaluate the object at the end
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        internal async Task <ContextObject> GetContextForPath(string path, Parser.ScopeData scopeData)
        {
            var elements = new Queue <string>();

            foreach (var m in PathFinder.Matches(path).OfType <Match>())
            {
                elements.Enqueue(m.Value);
            }

            return(await GetContextForPath(elements, scopeData));
        }
Beispiel #2
0
        private async Task <ContextObject> GetContextForPath(Queue <string> elements, Parser.ScopeData scopeData)
        {
            var retval = this;

            if (elements.Any())
            {
                var path       = elements.Dequeue();
                var preHandeld = HandlePathContext(elements, path);
                if (preHandeld != null)
                {
                    return(preHandeld);
                }

                if (path.StartsWith("~"))                 //go the root object
                {
                    var parent     = Parent;
                    var lastParent = parent;
                    while (parent != null)
                    {
                        parent = parent.Parent;
                        if (parent != null)
                        {
                            lastParent = parent;
                        }
                    }

                    if (lastParent != null)
                    {
                        retval = await lastParent.GetContextForPath(elements, scopeData);
                    }
                }
                else if (path.Equals("$recursion"))                 //go the root object
                {
                    retval = new ContextObject(Options, path)
                    {
                        Parent = this,
                        Value  = scopeData.PartialDepth.Count
                    };
                }
                else if (path.StartsWith(".."))                 //go one level up
                {
                    if (Parent != null)
                    {
                        var parentsRetVal = (await Parent.GetContextForPath(elements, scopeData));
                        if (parentsRetVal != null)
                        {
                            retval = parentsRetVal;
                        }
                        else
                        {
                            retval = await GetContextForPath(elements, scopeData);
                        }
                    }
                    else
                    {
                        retval = await GetContextForPath(elements, scopeData);
                    }
                }
                else if (path.StartsWith("?"))                 //enumerate ether an IDictionary, an cs object or an IEnumerable to a KeyValuePair array
                {
                    //ALWAYS return the context, even if the value is null.
                    var innerContext = new ContextObject(Options, path)
                    {
                        Parent = this
                    };
                    await EnsureValue();

                    switch (Value)
                    {
                    case IDictionary <string, object> dictList:
                        innerContext.Value = dictList.Select(e => e);
                        break;

                    //This is a draft that i have discarded as its more likely to enumerate a single IEnumerable with #each alone
                    //case IEnumerable ctx:
                    //	innerContext.Value = ctx.OfType<object>().Select((item, index) => new KeyValuePair<string, object>(index.ToString(), item));
                    //	break;
                    default:
                    {
                        if (Value != null)
                        {
                            innerContext.Value = Value
                                                 .GetType()
                                                 .GetTypeInfo()
                                                 .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                 .Where(e => !e.IsSpecialName && !e.GetIndexParameters().Any())
                                                 .Select(e => new KeyValuePair <string, object>(e.Name, e.GetValue(Value)));
                        }

                        break;
                    }
                    }

                    retval = await innerContext.GetContextForPath(elements, scopeData);
                }
                //TODO: handle array accessors and maybe "special" keys.
                else
                {
                    //ALWAYS return the context, even if the value is null.
                    var innerContext = new ContextObject(Options, path)
                    {
                        Parent = this
                    };
                    await EnsureValue();

                    if (Value is IDictionary <string, object> ctx)
                    {
                        ctx.TryGetValue(path, out var o);
                        innerContext.Value = o;
                    }
                    else if (Value != null)
                    {
                        var propertyInfo = Value.GetType().GetTypeInfo().GetProperty(path);
                        if (propertyInfo != null)
                        {
                            innerContext.Value = propertyInfo.GetValue(Value);
                        }
                    }

                    retval = await innerContext.GetContextForPath(elements, scopeData);
                }
            }

            return(retval);
        }