/// <summary> /// Initializes a new instance of the <see cref="Antmicro.Migrant.Serializer"/> class. /// </summary> /// <param name='settings'> /// Serializer's settings, can be null or not given, in that case default settings are /// used. /// </param> public Serializer(Settings settings = null) { if (settings == null) { settings = new Settings(); // default settings } this.settings = settings; writeMethodCache = new Dictionary <Type, DynamicMethod>(); objectsForSurrogates = new InheritanceAwareList <Delegate>(); surrogatesForObjects = new InheritanceAwareList <Delegate>(); readMethodCache = new Dictionary <Type, DynamicMethod>(); if (settings.SupportForISerializable) { ForObject <System.Runtime.Serialization.ISerializable>().SetSurrogate(x => new SurrogateForISerializable(x)); ForSurrogate <SurrogateForISerializable>().SetObject(x => x.Restore()); ForObject <Delegate>().SetSurrogate <Func <Delegate, object> >(null); //because Delegate implements ISerializable but we support it directly. } if (settings.SupportForIXmlSerializable) { ForObject <System.Xml.Serialization.IXmlSerializable>().SetSurrogate(x => new SurrogateForIXmlSerializable(x)); ForSurrogate <SurrogateForIXmlSerializable>().SetObject(x => x.Restore()); } }
/// <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(); } }
internal static void SwapObjectWithSurrogate(ref object o, InheritanceAwareList <Delegate> swapList) { var type = o.GetType(); foreach (var swapCandidate in swapList) { if (swapCandidate.Key.IsAssignableFrom(type)) { o = swapCandidate.Value.DynamicInvoke(new object[] { o }); break; } } }
internal static int GetSurrogateFactoryIdForType(Type type, InheritanceAwareList <Delegate> swapList) { var i = 0; foreach (var swapCandidate in swapList) { if (swapCandidate.Key.IsAssignableFrom(type)) { return(swapCandidate.Value == null ? -1 : i); } i++; } return(-1); }
/// <summary> /// Initializes a new instance of the <see cref="Antmicro.Migrant.ObjectReader" /> class. /// </summary> /// <param name='stream'> /// Stream from which objects will be read. /// </param> /// <param name='objectsForSurrogates'> /// Dictionary, containing callbacks that provide objects for given type of surrogate. Callbacks have to be of type Func<T, object> where /// typeof(T) is type of surrogate. /// </param> /// <param name='postDeserializationCallback'> /// Callback which will be called after deserialization of every unique object. Deserialized /// object is given in the callback's only parameter. /// </param> /// <param name='readMethods'> /// Cache in which generated read methods are stored and reused between instances of <see cref="Antmicro.Migrant.ObjectReader" />. /// Can be null if one does not want to use the cache. /// </param> /// <param name='isGenerating'> /// True if read methods are to be generated, false if one wants to use reflection. /// </param> /// <param name = "treatCollectionAsUserObject"> /// True if collection objects are to be deserialized without optimization (treated as normal user objects). /// </param> /// <param name="versionToleranceLevel"> /// Describes the tolerance level of this reader when handling discrepancies in type description (new or missing fields, etc.). /// </param> /// <param name="useBuffering"> /// True if buffering was used with the corresponding ObjectWriter or false otherwise - i.e. when no padding and buffering is used. /// </param> /// <param name="referencePreservation"> /// Tells deserializer whether open stream serialization preserved objects identieties between serialization. Note that this option should /// be consistent with what was used during serialization. /// </param> public ObjectReader(Stream stream, InheritanceAwareList <Delegate> objectsForSurrogates = null, Action <object> postDeserializationCallback = null, IDictionary <Type, DynamicMethod> readMethods = null, bool isGenerating = false, bool treatCollectionAsUserObject = false, VersionToleranceLevel versionToleranceLevel = 0, bool useBuffering = true, ReferencePreservation referencePreservation = ReferencePreservation.Preserve) { if (objectsForSurrogates == null) { objectsForSurrogates = new InheritanceAwareList <Delegate>(); } this.objectsForSurrogates = objectsForSurrogates; this.readMethodsCache = readMethods ?? new Dictionary <Type, DynamicMethod>(); this.useGeneratedDeserialization = isGenerating; typeList = new List <Type>(); methodList = new List <MethodInfo>(); postDeserializationHooks = new List <Action>(); this.postDeserializationCallback = postDeserializationCallback; this.treatCollectionAsUserObject = treatCollectionAsUserObject; delegatesCache = new Dictionary <Type, Func <int, object> >(); reader = new PrimitiveReader(stream, useBuffering); stamper = new TypeStampReader(reader, versionToleranceLevel); this.referencePreservation = referencePreservation; }
/// <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. /// </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. /// </param> /// <param name='isGenerating'> /// True if write methods are to be generated, false if one wants to use reflection. /// </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) { if(surrogatesForObjects == null) { surrogatesForObjects = new InheritanceAwareList<Delegate>(); } currentlyWrittenTypes = new Stack<Type>(); transientTypeCache = new Dictionary<Type, bool>(); writeMethods = new List<Action<PrimitiveWriter, object>>(); postSerializationHooks = new List<Action>(); this.writeMethodCache = writeMethodCache; this.isGenerating = isGenerating; this.surrogatesForObjects = surrogatesForObjects; typeIndices = new Dictionary<Type, int>(); methodIndices = new Dictionary<MethodInfo, int>(); this.stream = stream; this.preSerializationCallback = preSerializationCallback; this.postSerializationCallback = postSerializationCallback; 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(); } }