Example #1
0
        public ObjectTreeAnalysisResult(object objectToSearch, string propertyPath
                                        , IContractResolver contractResolver)
        {
            // construct the analysis result.

            // split the propertypath, and if necessary, remove the first
            // empty item (that's the case when it starts with a "/")
            var propertyPathTree = propertyPath.Split(
                new char[] { '/' },
                StringSplitOptions.RemoveEmptyEntries).ToList();
            object targetObject = objectToSearch;

            // we've now got a split up property tree "base/property/otherproperty/..."
            int lastPosition = 0;

            for (int i = 0; i < propertyPathTree.Count; i++)
            {
                // if the current target object is an ExpandoObject (IDictionary<string, object>),
                // we cannot use the ContractResolver.

                lastPosition = i;

                // if the current part of the path is numeric, this means we're trying
                // to get the propertyInfo of a specific object in an array.  To allow
                // for this, the previous value (targetObject) must be an IEnumerable, and
                // the position must exist.

                int numericValue = -1;
                if (int.TryParse(propertyPathTree[i], out numericValue))
                {
                    var element = GetElementAtFromObject(targetObject, numericValue);
                    if (element != null)
                    {
                        targetObject = element;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    var jsonContract = (JsonObjectContract)contractResolver
                                       .ResolveContract(targetObject.GetType());

                    // does the property exist?
                    var attemptedProperty = jsonContract.Properties.FirstOrDefault
                                                (p => string.Equals(p.PropertyName, propertyPathTree[i]
                                                                    , StringComparison.OrdinalIgnoreCase));

                    if (attemptedProperty != null)
                    {
                        // unless we're at the last item, we should continue searching.
                        // If we're at the last item, we need to stop
                        if (!(i == propertyPathTree.Count - 1))
                        {
                            targetObject = attemptedProperty.ValueProvider.GetValue(targetObject);
                        }
                    }
                    else
                    {
                        // property cannot be found
                        // Stop, and return invalid path.
                        break;
                    }
                }
            }

            var leftOverPath = propertyPathTree
                               .GetRange(lastPosition, propertyPathTree.Count - lastPosition);

            if (leftOverPath.Count == 1)
            {
                var jsonContract = (JsonObjectContract)contractResolver
                                   .ResolveContract(targetObject.GetType());

                var attemptedProperty = jsonContract.Properties.FirstOrDefault
                                            (p => string.Equals(p.PropertyName, leftOverPath.Last()
                                                                , StringComparison.OrdinalIgnoreCase));

                if (attemptedProperty == null)
                {
                    IsValidPathForAdd    = false;
                    IsValidPathForRemove = false;
                }
                else
                {
                    IsValidPathForAdd    = true;
                    IsValidPathForRemove = true;
                    JsonPatchProperty    = new Helpers.JsonPatchProperty(attemptedProperty, targetObject);
                    PropertyPathInParent = leftOverPath.Last();
                }
            }
            else
            {
                IsValidPathForAdd    = false;
                IsValidPathForRemove = false;
            }
        }
        public ObjectTreeAnalysisResult(object objectToSearch, string propertyPath
                                        , IContractResolver contractResolver)
        {
            // construct the analysis result.

            // split the propertypath, and if necessary, remove the first
            // empty item (that's the case when it starts with a "/")
            var propertyPathTree = propertyPath.Split(
                new char[] { '/' },
                StringSplitOptions.RemoveEmptyEntries).ToList();
            object targetObject = objectToSearch;

            // we've now got a split up property tree "base/property/otherproperty/..."
            int lastPosition = 0;

            for (int i = 0; i < propertyPathTree.Count; i++)
            {
                // if the current target object is an ExpandoObject (IDictionary<string, object>),
                // we cannot use the ContractResolver.

                lastPosition = i;

                // if the current part of the path is numeric, this means we're trying
                // to get the propertyInfo of a specific object in an array.  To allow
                // for this, the previous value (targetObject) must be an IEnumerable, and
                // the position must exist.

                int numericValue = -1;
                if (int.TryParse(propertyPathTree[i], out numericValue))
                {
                    var element = GetElementAtFromObject(targetObject, numericValue);
                    if (element != null)
                    {
                        targetObject = element;
                    }
                    else
                    {
                        break;
                    }
                }
                else if (propertyPathTree[i].StartsWith("[") && propertyPathTree[i].EndsWith("]"))
                {
                    // we are going to try a bit of bullshittery here.
                    // i would use something like dynamic linq, but this is a portable library. When i have time, i will split this out. Until then:
                    string exprString = propertyPathTree[i].Substring(1, propertyPathTree[i].Length - 2);
                    var    element    = ExpressionHelpers.GetElementAtFromObjectExpression(targetObject, exprString);
                    if (element != null)
                    {
                        targetObject = element;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    var jsonContract = (JsonObjectContract)contractResolver
                                       .ResolveContract(targetObject.GetType());

                    // does the property exist?
                    var attemptedProperty = jsonContract.Properties.FirstOrDefault
                                                (p => string.Equals(p.PropertyName, propertyPathTree[i]
                                                                    , StringComparison.OrdinalIgnoreCase));

                    if (attemptedProperty != null)
                    {
                        // unless we're at the last item, we should continue searching.
                        // If we're at the last item, we need to stop
                        if (!(i == propertyPathTree.Count - 1))
                        {
                            targetObject = attemptedProperty.ValueProvider.GetValue(targetObject);
                            if (targetObject == null)
                            {
                                throw new Exception($"Attempted to walk path '/{string.Join("/", propertyPathTree.GetRange(0, i + 1))}' on given '{objectToSearch.GetType().Name}' but encountered null");
                            }
                        }
                    }
                    else
                    {
                        // property cannot be found
                        // Stop, and return invalid path.
                        break;
                    }
                }
            }

            var leftOverPath = propertyPathTree
                               .GetRange(lastPosition, propertyPathTree.Count - lastPosition);

            if (leftOverPath.Count == 1)
            {
                var jsonContract = (JsonObjectContract)contractResolver
                                   .ResolveContract(targetObject.GetType());

                var attemptedProperty = jsonContract.Properties.FirstOrDefault
                                            (p => string.Equals(p.PropertyName, leftOverPath.Last()
                                                                , StringComparison.OrdinalIgnoreCase));

                if (attemptedProperty == null)
                {
                    if (leftOverPath.Last().StartsWith("[") && leftOverPath.Last().EndsWith("]"))
                    {
                        attemptedProperty = jsonContract.Properties.FirstOrDefault(p => string.Equals(p.PropertyName, propertyPathTree[lastPosition - 1], StringComparison.OrdinalIgnoreCase));
                        if (attemptedProperty != null)
                        {
                            IsValidPathForAdd    = false;
                            IsValidPathForRemove = true;
                            JsonPatchProperty    = new Helpers.JsonPatchProperty(attemptedProperty, targetObject);
                            PropertyPathInParent = leftOverPath.Last();
                        }
                        else
                        {
                            IsValidPathForAdd    = false;
                            IsValidPathForRemove = false;
                        }
                    }
                    else
                    {
                        IsValidPathForAdd    = false;
                        IsValidPathForRemove = false;
                    }
                }
                else
                {
                    IsValidPathForAdd    = true;
                    IsValidPathForRemove = true;
                    JsonPatchProperty    = new Helpers.JsonPatchProperty(attemptedProperty, targetObject);
                    PropertyPathInParent = leftOverPath.Last();
                }
            }
            else
            {
                IsValidPathForAdd    = false;
                IsValidPathForRemove = false;
            }
        }