public ObjectWriter(Stream stream, Action<object> preSerializationCallback = null, Action<object> postSerializationCallback = null, IDictionary<Type, Action<ObjectWriter, PrimitiveWriter, object>> writeMethods = null, SwapList surrogatesForObjects = null, bool isGenerating = true, bool treatCollectionAsUserObject = false, bool useBuffering = true, bool disableStamping = false, ReferencePreservation referencePreservation = ReferencePreservation.Preserve) { if(surrogatesForObjects == null) { surrogatesForObjects = new SwapList(); } currentlyWrittenTypes = new Stack<Type>(); this.writeMethods = writeMethods ?? new Dictionary<Type, Action<ObjectWriter, PrimitiveWriter, object>>(); postSerializationHooks = new List<Action>(); this.isGenerating = isGenerating; this.treatCollectionAsUserObject = treatCollectionAsUserObject; this.surrogatesForObjects = surrogatesForObjects; types = new IdentifiedElementsDictionary<TypeDescriptor>(this); Methods = new IdentifiedElementsDictionary<MethodDescriptor>(this); Assemblies = new IdentifiedElementsDictionary<AssemblyDescriptor>(this); Modules = new IdentifiedElementsDictionary<ModuleDescriptor>(this); this.preSerializationCallback = preSerializationCallback; this.postSerializationCallback = postSerializationCallback; writer = new PrimitiveWriter(stream, useBuffering); this.referencePreservation = referencePreservation; if(referencePreservation == ReferencePreservation.Preserve) { identifier = new ObjectIdentifier(); } touchTypeMethod = disableStamping ? (Func<Type, int>)TouchAndWriteTypeIdWithSimpleStamp : TouchAndWriteTypeIdWithFullStamp; }
public ObjectWriter(Stream stream, Serializer.WriteMethods writeMethods, Action<object> preSerializationCallback = null, Action<object> postSerializationCallback = null, SwapList surrogatesForObjects = null, SwapList objectsForSurrogates = null, bool treatCollectionAsUserObject = false, bool useBuffering = true, bool disableStamping = false, ReferencePreservation referencePreservation = ReferencePreservation.Preserve) { this.treatCollectionAsUserObject = treatCollectionAsUserObject; this.objectsForSurrogates = objectsForSurrogates; this.referencePreservation = referencePreservation; this.preSerializationCallback = preSerializationCallback; this.postSerializationCallback = postSerializationCallback; this.writeMethods = writeMethods; this.surrogatesForObjects = surrogatesForObjects ?? new SwapList(); parentObjects = new Dictionary<object, object>(); postSerializationHooks = new List<Action>(); types = new IdentifiedElementsDictionary<TypeDescriptor>(this); Methods = new IdentifiedElementsDictionary<MethodDescriptor>(this); Assemblies = new IdentifiedElementsDictionary<AssemblyDescriptor>(this); Modules = new IdentifiedElementsDictionary<ModuleDescriptor>(this); writer = new PrimitiveWriter(stream, useBuffering); if(referencePreservation == ReferencePreservation.Preserve) { identifier = new ObjectIdentifier(); } touchTypeMethod = disableStamping ? (Func<Type, int>)TouchAndWriteTypeIdWithSimpleStamp : TouchAndWriteTypeIdWithFullStamp; objectsWrittenInline = new HashSet<int>(); }
private void PrepareForNextWrite() { objectsWrittenInline.Clear(); parentObjects.Clear(); if(referencePreservation == ReferencePreservation.UseWeakReference) { identifierContext = identifier.GetContext(); } if(referencePreservation != ReferencePreservation.Preserve) { identifier = null; } }
public void WriteObject(object o) { if(o == null || Helpers.IsTransient(o.GetType())) { throw new ArgumentException("Cannot write a null object or a transient object."); } if(referencePreservation != ReferencePreservation.Preserve) { identifier = identifierContext == null ? new ObjectIdentifier() : new ObjectIdentifier(identifierContext); identifierContext = null; } try { var writtenBefore = identifier.Count; writeMethods.writeReferenceMethodsProvider.GetOrCreate(typeof(object))(this, o); if(writtenBefore != identifier.Count) { var refId = identifier.GetId(o); do { if(!objectsWrittenInline.Contains(refId)) { var obj = identifier.GetObject(refId); writer.Write(refId); InvokeCallbacksAndExecute(obj, WriteObjectInner); } refId++; } while(identifier.Count > refId); } } finally { for(var i = identifier.Count - 1; i >= 0; i--) { Completed(identifier.GetObject(i)); } foreach(var postHook in postSerializationHooks) { postHook(); } PrepareForNextWrite(); } }
private void PrepareForNextWrite() { if(referencePreservation != ReferencePreservation.DoNotPreserve) { identifierCountPreviousSession = identifier.Count; } else { inlineWritten.Clear(); } currentlyWrittenTypes.Clear(); if(referencePreservation == ReferencePreservation.UseWeakReference) { identifierContext = identifier.GetContext(); } if(referencePreservation != ReferencePreservation.Preserve) { identifier = null; } }
/// <summary> /// Writes the given object along with the ones referenced by it. /// </summary> /// <param name='o'> /// The object to write. /// </param> public void WriteObject(object o) { if(o == null || Helpers.CheckTransientNoCache(o.GetType())) { throw new ArgumentException("Cannot write a null object or a transient object."); } objectsWrittenThisSession = 0; if(referencePreservation != ReferencePreservation.Preserve) { identifier = identifierContext == null ? new ObjectIdentifier() : new ObjectIdentifier(identifierContext); identifierContext = null; } var identifiersCount = identifier.Count; identifier.GetId(o); var firstObjectIsNew = identifiersCount != identifier.Count; try { // first object is always written InvokeCallbacksAndWriteObject(o); if(firstObjectIsNew) { objectsWrittenThisSession++; } while(identifier.Count - identifierCountPreviousSession > objectsWrittenThisSession) { if(!inlineWritten.Contains(identifierCountPreviousSession + objectsWrittenThisSession)) { InvokeCallbacksAndWriteObject(identifier[identifierCountPreviousSession + objectsWrittenThisSession]); } objectsWrittenThisSession++; } } finally { foreach(var postHook in postSerializationHooks) { postHook(); } PrepareForNextWrite(); } }
/// <summary> /// Initializes a new instance of the <see cref="Antmicro.Migrant.ObjectWriter" /> class. /// </summary> /// <param name='stream'> /// Stream to which data will be written. /// </param> /// <param name='preSerializationCallback'> /// Callback which is called once on every unique object before its serialization. Contains this object in its only parameter. /// </param> /// <param name='postSerializationCallback'> /// Callback which is called once on every unique object after its serialization. Contains this object in its only parameter. /// </param> /// <param name='writeMethodCache'> /// Cache in which generated write methods are stored and reused between instances of <see cref="Antmicro.Migrant.ObjectWriter" />. /// Can be null if one does not want to use the cache. Note for the life of the cache you always have to provide the same /// <paramref name="surrogatesForObjects"/>. /// </param> /// <param name='surrogatesForObjects'> /// Dictionary, containing callbacks that provide surrogate for given type. Callbacks have to be of type Func<T, object> where /// typeof(T) is given type. Note that the list always have to be in sync with <paramref name="writeMethodCache"/>. /// </param> /// <param name='isGenerating'> /// True if write methods are to be generated, false if one wants to use reflection. /// </param> /// <param name = "treatCollectionAsUserObject"> /// True if collection objects are to be serialized without optimization (treated as normal user objects). /// </param> /// <param name="useBuffering"> /// True if buffering is used. False if all writes should directly go to the stream and no padding should be used. /// </param> /// <param name="referencePreservation"> /// Tells serializer how to treat object identity between the calls to <see cref="Antmicro.Migrant.ObjectWriter.WriteObject" />. /// </param> public ObjectWriter(Stream stream, Action<object> preSerializationCallback = null, Action<object> postSerializationCallback = null, IDictionary<Type, DynamicMethod> writeMethodCache = null, InheritanceAwareList<Delegate> surrogatesForObjects = null, bool isGenerating = true, bool treatCollectionAsUserObject = false, bool useBuffering = true, ReferencePreservation referencePreservation = ReferencePreservation.Preserve) { if(surrogatesForObjects == null) { surrogatesForObjects = new InheritanceAwareList<Delegate>(); } currentlyWrittenTypes = new Stack<Type>(); transientTypeCache = new Dictionary<Type, bool>(); writeMethods = new Dictionary<Type, Action<PrimitiveWriter, object>>(); postSerializationHooks = new List<Action>(); this.writeMethodCache = writeMethodCache; this.isGenerating = isGenerating; this.treatCollectionAsUserObject = treatCollectionAsUserObject; this.surrogatesForObjects = surrogatesForObjects; typeIndices = new Dictionary<TypeDescriptor, int>(); methodIndices = new Dictionary<MethodInfo, int>(); assemblyIndices = new Dictionary<AssemblyDescriptor, int>(); this.preSerializationCallback = preSerializationCallback; this.postSerializationCallback = postSerializationCallback; writer = new PrimitiveWriter(stream, useBuffering); inlineWritten = new HashSet<int>(); this.referencePreservation = referencePreservation; if(referencePreservation == ReferencePreservation.Preserve) { identifier = new ObjectIdentifier(); } }