示例#1
0
        /// <summary>
        /// Serialization text on the EntitySet level turns into a JSON array, composed of individual object-per-collection member.
        /// The output format is lighter-weight than the portable format (no schema).
        /// </summary>
        /// <param name="mode"></param>
        /// <returns></returns>
        public string GetSerializationText(SerializationMode?mode = null)
        {
            StringBuilder sb      = new StringBuilder(4096);
            var           actmode = mode.GetValueOrDefault(CEF.CurrentServiceScope.Settings.SerializationMode);
            var           st      = new SerializationVisitTracker();

            CEF.CurrentServiceScope.ReconcileModifiedState(null);

            using (var jw = new JsonTextWriter(new StringWriter(sb)))
            {
                jw.WriteStartArray();

                foreach (var i in this)
                {
                    var iw = i.AsInfraWrapped();
                    var rs = iw.GetRowState();

                    if ((rs != ObjectState.Unchanged && rs != ObjectState.Unlinked) || ((actmode & SerializationMode.OnlyChanged) == 0))
                    {
                        CEF.CurrentPCTService()?.SaveContents(jw, i, actmode, st);
                    }
                }

                jw.WriteEndArray();
            }

            return(sb.ToString());
        }
示例#2
0
        /// <summary>
        /// For a given object, persist its JSON representation to stream.
        /// </summary>
        /// <param name="tw"></param>
        /// <param name="o"></param>
        /// <param name="mode"></param>
        /// <param name="visits"></param>
        /// <returns></returns>
        public bool SaveContents(JsonTextWriter tw, object o, SerializationMode mode, SerializationVisitTracker visits)
        {
            if (visits.Objects.Contains(o))
            {
                return(true);
            }

            bool include = true;

            if ((mode & SerializationMode.OnlyChanged) != 0)
            {
                // Point of this? if we have object graph a->b->c, if c is modified, both a and b need to be included even if unmodified to support proper hierarchy
                include = RequiresPersistenceForChanges(o, mode, new ConcurrentDictionary <object, bool>(Globals.DefaultCollectionConcurrencyLevel, Globals.DefaultDictionaryCapacity));
            }

            if (include)
            {
                WriteSerializationText(tw, o, mode, visits);
            }

            visits.Objects.Add(o);

            var wot = o.AsInfraWrapped().GetWrappedObject()?.GetType() ?? o.GetBaseType();

            if (!visits.Types.Contains(wot))
            {
                visits.Types.Add(wot);
            }

            return(include);
        }
示例#3
0
        private void WriteSerializationText(JsonTextWriter tw, object o, SerializationMode mode, SerializationVisitTracker visits)
        {
            var iw = o.AsInfraWrapped(false);

            if (iw != null)
            {
                tw.WriteStartObject();

                var wot = iw.GetWrappedObject()?.GetType() ?? iw.GetBaseType();

                // We only really want/need to include type info on outermost objects (session scope level only), so reset this for all nested objects
                var nextmode = (SerializationMode)((int)mode & (-1 ^ (int)SerializationMode.IncludeType));

                if ((mode & SerializationMode.IncludeType) != 0)
                {
                    tw.WritePropertyName(Globals.SerializationTypePropertyName);
                    tw.WriteValue(o.GetType().AssemblyQualifiedName);
                }

                // Attempt to push enumerable types to the "end"
                foreach (var kvp in (from a in iw.GetAllValues() orderby a.Value is IEnumerable ? 1 : 0 select a))
                {
                    // If it's enumerable, recurse each item
                    // TODO - better way to detect primitive type like string w/o hardcoding??
                    if (kvp.Value is IEnumerable && kvp.Value.GetType() != typeof(string))
                    {
                        tw.WritePropertyName(kvp.Key);
                        tw.WriteStartArray();

                        var asEnum = (kvp.Value as IEnumerable).GetEnumerator();

                        while (asEnum.MoveNext())
                        {
                            var i = asEnum.Current;

                            // We only need to do this for tracked objects, for now we only do for value types or non-system (TODO)
                            if (i == null || i.GetType().IsValueType || i.GetType().FullName.StartsWith("System."))
                            {
                                tw.WriteValue(i);
                            }
                            else
                            {
                                if ((mode & SerializationMode.SingleLevel) == 0)
                                {
                                    var iw2 = i.AsInfraWrapped();

                                    if (iw2 != null)
                                    {
                                        SaveContents(tw, iw2, nextmode, visits);
                                    }
                                    else
                                    {
                                        if (i.GetType().IsSerializable)
                                        {
                                            tw.WriteValue(i);
                                        }
                                    }
                                }
                            }
                        }

                        tw.WriteEndArray();
                    }
                    else
                    {
                        // If it's a tracked object, recurse
                        if (kvp.Value != null && !kvp.Value.GetType().IsValueType&& CEF.CurrentServiceScope.GetTrackedByWrapperOrTarget(kvp.Value) != null)
                        {
                            if ((mode & SerializationMode.SingleLevel) == 0)
                            {
                                var iw2 = kvp.Value.AsInfraWrapped();

                                if (iw2 != null)
                                {
                                    tw.WritePropertyName(kvp.Key);
                                    SaveContents(tw, iw2, nextmode, visits);
                                }
                            }
                        }
                        else
                        {
                            if ((mode & SerializationMode.ExtendedInfoAsShadowProps) != 0)
                            {
                                var rs = iw.GetRowState();

                                if (rs == ObjectState.Modified || rs == ObjectState.ModifiedPriority)
                                {
                                    var ov = iw.GetOriginalValue(kvp.Key, false);

                                    if (ov != null)
                                    {
                                        tw.WritePropertyName("\\\\" + kvp.Key);
                                        tw.WriteValue(ov);
                                    }
                                }

                                // We write out schema metadata only when see a type for the first time
                                if (!visits.Types.Contains(wot))
                                {
                                    var pb = wot.GetProperty(kvp.Key);

                                    // Preferred data type
                                    var pt = (from a in iw.GetAllPreferredTypes() where a.Key == kvp.Key select a.Value).FirstOrDefault() ?? pb?.PropertyType;

                                    if (pt != null)
                                    {
                                        tw.WritePropertyName("\\+" + kvp.Key);
                                        tw.WriteValue(pt.AssemblyQualifiedName);

                                        // Is writeable
                                        tw.WritePropertyName("\\-" + kvp.Key);
                                        tw.WriteValue(pb?.CanWrite);
                                    }
                                }
                            }

                            if (kvp.Value != null || (mode & SerializationMode.IncludeNull) != 0)
                            {
                                if (((mode & SerializationMode.IncludeReadOnlyProps) != 0) || (wot.GetProperty(kvp.Key)?.CanWrite).GetValueOrDefault(true))
                                {
                                    if (((mode & SerializationMode.OnlyCLRProperties) == 0) || (wot.GetProperty(kvp.Key)?.CanRead).GetValueOrDefault(false))
                                    {
                                        var aud = CEF.CurrentAuditService();

                                        if (aud != null)
                                        {
                                            if (((mode & SerializationMode.OriginalForConcurrency) == 0) || (string.Compare(aud.LastUpdatedDateField, kvp.Key, true) != 0 && string.Compare(aud.IsDeletedField, kvp.Key, true) != 0))
                                            {
                                                if (kvp.Value == null || kvp.Value.GetType().IsSerializable)
                                                {
                                                    tw.WritePropertyName(kvp.Key);
                                                    tw.WriteValue(kvp.Value);
                                                }
                                            }
                                            else
                                            {
                                                // Only need to send original date - do not send isdeleted at all
                                                if (string.Compare(aud.IsDeletedField, kvp.Key, true) != 0)
                                                {
                                                    var rs = iw.GetRowState();

                                                    if (rs != ObjectState.Added && rs != ObjectState.Unlinked)
                                                    {
                                                        var val = iw.GetOriginalValue(kvp.Key, false);

                                                        if (val != null)
                                                        {
                                                            tw.WritePropertyName(kvp.Key);
                                                            tw.WriteValue(val);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if ((mode & SerializationMode.ExtendedInfoAsShadowProps) != 0)
                {
                    tw.WritePropertyName("_ot_");
                    tw.WriteValue(wot.Name);
                }

                // Allows for inclusion of object state, etc.
                iw.FinalizeObjectContents(tw, mode);

                tw.WriteEndObject();
            }
            else
            {
                tw.WriteValue(o);
            }
        }