Esempio n. 1
0
        private static IDictionary <string, object> ExtractState(object o, HashSet <object> visited)
        {
            MetaType metaType = MetaType.GetMetaType(o.GetType());
            Dictionary <string, object> extractedState = new Dictionary <string, object>();

            if (visited.Contains(o))
            {
                throw new InvalidOperationException(Resource.CyclicReferenceError);
            }
            else
            {
                visited.Add(o);
            }

            foreach (MetaMember metaMember in metaType.DataMembers)
            {
                object value = metaMember.GetValue(o);

                if (value != null && metaMember.IsComplex && !metaMember.IsCollection)
                {
                    value = ExtractState(value, visited);
                }

                extractedState[metaMember.Name] = value;
            }

            return(extractedState);
        }
Esempio n. 2
0
        /// <summary>
        /// For the specified Type and original state map, this method returns a state map containing
        /// only values that should be roundtripped (based on RoundtripOriginal member attribution).
        /// </summary>
        /// <param name="type">The Type the state map is for.</param>
        /// <param name="state">The original state map.</param>
        /// <returns>The state map containing only values that should be rountripped.</returns>
        internal static IDictionary <string, object> ExtractRoundtripState(Type type, IDictionary <string, object> state)
        {
            MetaType metaType = MetaType.GetMetaType(type);
            Dictionary <string, object> resultRoundtripState = new Dictionary <string, object>();

            foreach (MetaMember metaMember in metaType.DataMembers)
            {
                if (!metaMember.IsRoundtripMember)
                {
                    // only copy RTO state
                    continue;
                }

                if (!metaMember.IsComplex)
                {
                    // for simple members, just copy the state over directly
                    resultRoundtripState.Add(metaMember.Name, state[metaMember.Name]);
                }
                else
                {
                    // if the member is complex we need to preprocess and apply values recursively
                    if (!metaMember.IsCollection)
                    {
                        IDictionary <string, object> originalState = (IDictionary <string, object>)state[metaMember.Name];
                        if (originalState != null)
                        {
                            IDictionary <string, object> roundtripState = ExtractRoundtripState(metaMember.PropertyType, originalState);
                            resultRoundtripState.Add(metaMember.Name, roundtripState);
                        }
                    }
                    else
                    {
                        IEnumerable originalCollection = (IEnumerable)state[metaMember.Name];
                        if (originalCollection != null)
                        {
                            Type  elementType   = TypeUtility.GetElementType(metaMember.PropertyType);
                            IList newCollection = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elementType));

                            // Create a copy collection and copy elements recursively. Since Entity Extract/Apply state isn't
                            // deep through complex type collections, we have to recursively do the RTO filtering here.
                            foreach (object element in originalCollection)
                            {
                                IDictionary <string, object> originalState = ObjectStateUtility.ExtractState(element);
                                if (originalState != null)
                                {
                                    IDictionary <string, object> roundtripState = ExtractRoundtripState(elementType, originalState);
                                    object newInstance = Activator.CreateInstance(elementType);
                                    ObjectStateUtility.ApplyState(newInstance, roundtripState);
                                    newCollection.Add(newInstance);
                                }
                            }

                            resultRoundtripState.Add(metaMember.Name, newCollection);
                        }
                    }
                }
            }

            return(resultRoundtripState);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ValidationResultCollection"/> class.
        /// </summary>
        /// <param name="parent">The parent instance hosting this collection.</param>
        internal ValidationResultCollection(object parent)
        {
            this._results           = new List <ValidationResult>();
            this._hasErrors         = false;
            this._propertiesInError = Enumerable.Empty <string>();
            this._parent            = parent;

            if (this._parent != null)
            {
                this._parentMetaType = MetaType.GetMetaType(this._parent.GetType());
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Applies the specified state to the specified object taking the specified LoadBehavior into account.
        /// </summary>
        /// <param name="o">The object to apply state to.</param>
        /// <param name="stateToApply">The state dictionary.</param>
        /// <param name="originalState">The original state map for the modified object.</param>
        /// <param name="loadBehavior">The LoadBehavior to govern property merge behavior.</param>
        internal static void ApplyState(object o, IDictionary <string, object> stateToApply, IDictionary <string, object> originalState, LoadBehavior loadBehavior)
        {
            if (loadBehavior == LoadBehavior.KeepCurrent)
            {
                return;
            }

            MetaType metaType = MetaType.GetMetaType(o.GetType());

            bool isMerging = (o as Entity) == null ? (o as ComplexObject) != null && (o as ComplexObject).IsMergingState : (o as Entity).IsMergingState;

            foreach (MetaMember metaMember in metaType.DataMembers)
            {
                PropertyInfo propertyInfo = metaMember.Member;
                object       newValue;

                if ((isMerging && metaMember.IsMergable || !isMerging) && stateToApply.TryGetValue(propertyInfo.Name, out newValue))
                {
                    if (newValue != null && metaMember.IsComplex && !metaMember.IsCollection)
                    {
                        object currValue = propertyInfo.GetValue(o, null);
                        IDictionary <string, object> newValueState = (IDictionary <string, object>)newValue;
                        if (currValue != null)
                        {
                            // if the current and new values are both non-null, we have to do a merge
                            object complexTypeOriginalValues = null;
                            if (originalState != null)
                            {
                                originalState.TryGetValue(propertyInfo.Name, out complexTypeOriginalValues);
                            }
                            ApplyState(currValue, newValueState, (IDictionary <string, object>)complexTypeOriginalValues, loadBehavior);
                        }
                        else
                        {
                            // We do this lazy to avoid rehydrating the instance if we don't have to
                            Lazy <object> lazy = new Lazy <object>(
                                delegate
                            {
                                // Rehydrate an instance from the state dictionary.
                                object newInstance = Activator.CreateInstance(propertyInfo.PropertyType);
                                ApplyState(newInstance, newValueState);
                                return(newInstance);
                            });
                            ApplyValue(o, lazy, propertyInfo, originalState, loadBehavior);
                        }
                    }
                    else
                    {
                        ApplyValue(o, newValue, propertyInfo, originalState, loadBehavior);
                    }
                }
            }  // end foreach
        }