예제 #1
0
        /// <summary>
        /// Copies the changed property values from the underlying entity (accessible via <see cref="GetInstance()" />)
        /// to the <paramref name="original"/> entity recursively.
        /// </summary>
        /// <param name="original">The entity to be updated.</param>
        public void CopyChangedValues(T original)
        {
            if (original == null)
            {
                throw Error.ArgumentNull(nameof(original));
            }

            // Delta parameter type cannot be derived type of original
            // to prevent unrecognizable information from being applied to original resource.
            if (!_structuredType.IsAssignableFrom(original.GetType()))
            {
                throw Error.Argument(nameof(original), SRResources.DeltaTypeMismatch, _structuredType, original.GetType());
            }

            RuntimeHelpers.EnsureSufficientExecutionStack();

            // For regular non-structural properties at current level.
            PropertyAccessor <T>[] propertiesToCopy =
                _changedProperties.Intersect(_updatableProperties).Select(s => _allProperties[s]).ToArray();
            foreach (PropertyAccessor <T> propertyToCopy in propertiesToCopy)
            {
                propertyToCopy.Copy(_instance, original);
            }

            CopyChangedDynamicValues(original);

            // For nested resources.
            foreach (string nestedResourceName in _deltaNestedResources.Keys)
            {
                // Patch for each nested resource changed under this T.
                dynamic deltaNestedResource    = _deltaNestedResources[nestedResourceName];
                dynamic originalNestedResource = null;
                if (!TryGetPropertyRef(original, nestedResourceName, out originalNestedResource))
                {
                    throw Error.Argument(nestedResourceName, SRResources.DeltaNestedResourceNameNotFound,
                                         nestedResourceName, original.GetType());
                }

                if (originalNestedResource == null)
                {
                    // When patching original target of null value, directly set nested resource.
                    dynamic deltaObject = _deltaNestedResources[nestedResourceName];
                    dynamic instance    = deltaObject.GetInstance();

                    // Recursively patch up the instance with the nested resources.
                    deltaObject.CopyChangedValues(instance);

                    _allProperties[nestedResourceName].SetValue(original, instance);
                }
                else
                {
                    // Recursively patch the subtree.
                    bool isDeltaType = DeltaHelper.IsDeltaOfT(deltaNestedResource.GetType());
                    Contract.Assert(isDeltaType, nestedResourceName + "'s corresponding value should be Delta<T> type but is not.");

                    deltaNestedResource.CopyChangedValues(originalNestedResource);
                }
            }
        }
예제 #2
0
        /// <inheritdoc/>
        public override bool TryGetPropertyValue(string name, out object value)
        {
            if (name == null)
            {
                throw Error.ArgumentNull("name");
            }

            if (_dynamicDictionaryPropertyinfo != null)
            {
                if (_dynamicDictionaryCache == null)
                {
                    _dynamicDictionaryCache =
                        GetDynamicPropertyDictionary(_dynamicDictionaryPropertyinfo, _instance, create: false);
                }

                if (_dynamicDictionaryCache != null && _dynamicDictionaryCache.TryGetValue(name, out value))
                {
                    return(true);
                }
            }

            if (this._deltaNestedResources.ContainsKey(name))
            {
                // If this is a nested resource, get the value from the dictionary of nested resources.
                object deltaNestedResource = _deltaNestedResources[name];

                Contract.Assert(deltaNestedResource != null, "deltaNestedResource != null");
                Contract.Assert(DeltaHelper.IsDeltaOfT(deltaNestedResource.GetType()));

                // Get the Delta<{NestedResourceType}>._instance using Reflection.
                FieldInfo field = deltaNestedResource.GetType().GetField("_instance", BindingFlags.NonPublic | BindingFlags.Instance);
                Contract.Assert(field != null, "field != null");
                value = field.GetValue(deltaNestedResource);
                return(true);
            }
            else
            {
                // try to retrieve the value of property.
                PropertyAccessor <T> cacheHit;
                if (_allProperties.TryGetValue(name, out cacheHit))
                {
                    value = cacheHit.GetValue(_instance);
                    return(true);
                }
            }

            value = null;
            return(false);
        }
예제 #3
0
        /// <summary>
        /// Attempts to get the value of the nested Property called <paramref name="name"/> from the underlying resource.
        /// <remarks>
        /// Only properties that exist on Entity can be retrieved.
        /// Only modified nested properties can be retrieved.
        /// The nested Property type will be <see cref="IDelta"/> of its defined type.
        /// </remarks>
        /// </summary>
        /// <param name="name">The name of the nested Property</param>
        /// <param name="value">The value of the nested Property</param>
        /// <returns><c>True</c> if the Property was found and is a nested Property</returns>
        internal bool TryGetNestedPropertyValue(string name, out object value)
        {
            if (name == null)
            {
                throw Error.ArgumentNull(nameof(name));
            }

            if (!_deltaNestedResources.ContainsKey(name))
            {
                value = null;
                return(false);
            }

            // This is a nested resource, the value returned must be an IDelta<T>
            // from the dictionary of nested resources to allow the traversal of
            // hierarchies of Delta<T>.
            object deltaNestedResource = _deltaNestedResources[name];

            Contract.Assert(deltaNestedResource != null, "deltaNestedResource != null");
            Contract.Assert(DeltaHelper.IsDeltaOfT(deltaNestedResource.GetType()));

            value = deltaNestedResource;
            return(true);
        }