예제 #1
0
        /// <summary>
        ///     Clones the ContextObject into a new Detached object
        /// </summary>
        /// <returns></returns>
        public virtual ContextObject CloneForEdit(object newValue)
        {
            var contextClone = new ContextObject(_key, this, newValue)             //note: Parent must be the original context so we can traverse up to an unmodified context
            {
                _isNaturalContext = false,
            };

            return(contextClone);
        }
예제 #2
0
        /// <summary>
        ///     Clones the ContextObject into a new Detached object
        /// </summary>
        /// <returns></returns>
        public virtual ContextObject Copy()
        {
            var contextClone = new ContextObject(_key, _parent, _value)             //note: Parent must be the original context so we can traverse up to an unmodified context
            {
                _isNaturalContext = true,
            };

            return(contextClone);
        }
예제 #3
0
        /// <summary>
        ///     Clones the ContextObject into a new Detached object
        /// </summary>
        /// <returns></returns>
        public virtual ContextObject CloneForEdit()
        {
            var contextClone = new ContextObject(Options, Key, this, _value)             //note: Parent must be the original context so we can traverse up to an unmodified context
            {
                IsNaturalContext = false,
            };

            return(contextClone);
        }
예제 #4
0
 /// <summary>
 ///     ctor
 /// </summary>
 /// <param name="index">the current index of the item inside the collection</param>
 /// <param name="last">true if its the last item</param>
 /// <param name="options"></param>
 /// <param name="key"></param>
 public ContextCollection(long index,
                          bool last,
                          string key,
                          ContextObject parent,
                          object value)
     : base(key, parent, value)
 {
     Index = index;
     Last  = last;
 }
예제 #5
0
 /// <summary>
 ///     ctor
 /// </summary>
 /// <param name="index">the current index of the item inside the collection</param>
 /// <param name="last">true if its the last item</param>
 /// <param name="options"></param>
 /// <param name="key"></param>
 public ContextCollection(long index,
                          bool last,
                          [NotNull] ParserOptions options,
                          string key,
                          [CanBeNull] ContextObject parent,
                          object value)
     : base(options, key, parent, value)
 {
     Index = index;
     Last  = last;
 }
예제 #6
0
        internal ContextObject LoopContextTraversable(Traversable elements,
                                                      ScopeData scopeData,
                                                      IMorestachioExpression morestachioExpression)
        {
            ContextObject context = this;

            while (elements != null && elements.HasValue)
            {
                context  = context.GetContextForPathInternal(elements, scopeData, morestachioExpression);
                elements = elements.Next();
            }

            return(context);
        }
예제 #7
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="ContextObject" /> class.
        /// </summary>
        public ContextObject([NotNull] ParserOptions options, [NotNull] string key, [CanBeNull] ContextObject parent,
                             object value)
        {
            Options = options ?? throw new ArgumentNullException(nameof(options));
            Key     = key;
            Parent  = parent;
            _value  = value;
            if (Parent != null)
            {
                CancellationToken = Parent.CancellationToken;
            }

            IsNaturalContext = Parent?.IsNaturalContext ?? true;
        }
예제 #8
0
        internal ContextObject ExecuteObjectSelector(string key, Type type, ScopeData scopeData)
        {
            ContextObject innerContext = null;

            if (!scopeData.ParserOptions.HandleDictionaryAsObject && _value is IDictionary <string, object> dictList)
            {
                innerContext = scopeData.ParserOptions.CreateContextObject(key, dictList.Select(e => e), this);
            }
            else
            {
                if (_value != null)
                {
                    innerContext = scopeData.ParserOptions.CreateContextObject(key, type
                                                                               .GetTypeInfo()
                                                                               .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                                               .Where(e => !e.IsSpecialName && !e.GetIndexParameters().Any())
                                                                               .Select(e => new KeyValuePair <string, object>(e.Name, e.GetValue(Value))),
                                                                               this);
                }
            }

            return(innerContext ?? this);
        }
예제 #9
0
 /// <inheritdoc />
 public PartialContextObject(string key, ContextObject parent, object value) : base(key, parent, value)
 {
 }
 /// <inheritdoc />
 public PartialContextObject([NotNull] ParserOptions options, [NotNull] string key, [CanBeNull] ContextObject parent, object value) : base(options, key, parent, value)
 {
 }
예제 #11
0
        private async ContextObjectPromise GetContextForPathInternal(
            Traversable elements,
            ScopeData scopeData,
            IMorestachioExpression morestachioExpression)
        {
            var retval = this;

            if (elements == null)
            {
                return(retval);
            }

            var preHandeld = HandlePathContext(elements, elements.Current, morestachioExpression, scopeData);

            if (preHandeld != null)
            {
                return(preHandeld);
            }

            var type = Value?.GetType();

            if (elements.Current.Value == PathType.RootSelector)             //go the root object
            {
                var parent     = Parent ?? this;
                var lastParent = parent;
                while (parent != null)
                {
                    parent = parent.Parent;
                    if (parent != null)
                    {
                        lastParent = parent;
                    }
                }

                if (lastParent != null)
                {
                    retval = await lastParent.GetContextForPathInternal(elements.Next(), scopeData,
                                                                        morestachioExpression);
                }
            }
            else if (elements.Current.Value == PathType.ParentSelector)             //go one level up
            {
                if (Parent != null)
                {
                    var           parent        = FindNextNaturalContextObject();
                    ContextObject parentsRetVal = null;
                    if (parent != null && parent.Parent != null)
                    {
                        parentsRetVal = await parent.Parent
                                        .GetContextForPathInternal(elements.Next(), scopeData, morestachioExpression);
                    }

                    if (parentsRetVal != null)
                    {
                        retval = parentsRetVal;
                    }
                    else
                    {
                        retval = await GetContextForPathInternal(elements.Next(), scopeData, morestachioExpression);
                    }
                }
                else
                {
                    retval = await GetContextForPathInternal(elements.Next(), scopeData, morestachioExpression);
                }
            }
            else if (elements.Current.Value == PathType.ObjectSelector)
            //enumerate ether an IDictionary, an cs object or an IEnumerable to a KeyValuePair array
            {
                //await EnsureValue();
                if (Value is null)
                {
                    return(Options.CreateContextObject("x:null", CancellationToken, null));
                }

                //ALWAYS return the context, even if the value is null.
                ContextObject innerContext = null;
                switch (Value)
                {
                case IDictionary <string, object> dictList:
                    innerContext = Options.CreateContextObject(elements.Current.Key, CancellationToken,
                                                               dictList.Select(e => e), this);
                    break;

                default:
                {
                    if (Value != null)
                    {
                        innerContext = Options.CreateContextObject(elements.Current.Key, CancellationToken,
                                                                   type
                                                                   .GetTypeInfo()
                                                                   .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                                   .Where(e => !e.IsSpecialName && !e.GetIndexParameters().Any())
                                                                   .Select(e => new KeyValuePair <string, object>(e.Name, e.GetValue(Value))),
                                                                   this);
                    }

                    break;
                }
                }

                retval = await innerContext.GetContextForPathInternal(elements.Next(), scopeData,
                                                                      morestachioExpression);
            }
            else if (elements.Current.Value == PathType.Boolean)
            {
                if (elements.Current.Key == "true" || elements.Current.Key == "false")
                {
                    var booleanContext =
                        Options.CreateContextObject(".", CancellationToken, elements.Current.Key == "true", this);
                    booleanContext.IsNaturalContext = IsNaturalContext;
                    return(await booleanContext.GetContextForPathInternal(elements.Next(), scopeData,
                                                                          morestachioExpression));
                }
            }
            else if (elements.Current.Value == PathType.Null)
            {
                return(Options.CreateContextObject("x:null", CancellationToken, null, null));
            }
            else if (elements.Current.Value == PathType.DataPath)
            {
                //await EnsureValue();
                if (Value is null)
                {
                    return(Options.CreateContextObject("x:null", CancellationToken, null));
                }
                //TODO: handle array accessors and maybe "special" keys.
                //ALWAYS return the context, even if the value is null.

                var innerContext = Options.CreateContextObject(elements.Current.Key, CancellationToken, null, this);
                if (Options.ValueResolver?.CanResolve(type, Value, elements.Current.Key, innerContext) == true)
                {
                    innerContext._value = Options.ValueResolver.Resolve(type, Value, elements.Current.Key, innerContext);
                }
                else if (!Options.HandleDictionaryAsObject && Value is IDictionary <string, object> ctx)
                {
                    if (!ctx.TryGetValue(elements.Current.Key, out var o))
                    {
                        Options.OnUnresolvedPath(new InvalidPathEventArgs(this, morestachioExpression,
                                                                          elements.Current.Key, Value?.GetType()));
                    }

                    innerContext._value = o;
                }
                else if (Value is IMorestachioPropertyResolver cResolver)
                {
                    if (!cResolver.TryGetValue(elements.Current.Key, out var o))
                    {
                        Options.OnUnresolvedPath(new InvalidPathEventArgs(this, morestachioExpression,
                                                                          elements.Current.Key, Value?.GetType()));
                    }

                    innerContext._value = o;
                }
                else if (Value != null)
                {
                    if (Value is ICustomTypeDescriptor descriptor)
                    {
                        var propertyDescriptor = descriptor.GetProperties().Find(elements.Current.Key, false);
                        if (propertyDescriptor != null)
                        {
                            innerContext._value = propertyDescriptor.GetValue(Value);
                        }
                        else
                        {
                            Options.OnUnresolvedPath(new InvalidPathEventArgs(this, morestachioExpression,
                                                                              elements.Current.Key, Value?.GetType()));
                        }
                    }
                    else
                    {
                        var propertyInfo = type.GetTypeInfo().GetProperty(elements.Current.Key);
                        if (propertyInfo != null)
                        {
                            innerContext._value = propertyInfo.GetValue(Value);
                        }
                        else
                        {
                            Options.OnUnresolvedPath(new InvalidPathEventArgs(this, morestachioExpression,
                                                                              elements.Current.Key, Value?.GetType()));
                        }
                    }
                }

                retval = await innerContext.GetContextForPathInternal(elements.Next(), scopeData,
                                                                      morestachioExpression);
            }

            return(retval);
        }