/// <summary> /// Called by serializer when recursing to base classes or /// class member variables to duplicate the context args of /// the caller so caller isn't unexpectedly affected by logic /// in the child processing /// </summary> /// <returns></returns> public TypeSerializationArgs Clone() { TypeSerializationArgs clone = new TypeSerializationArgs(); clone.Writer = this.Writer; clone.Reader = this.Reader; clone.Flags = this.Flags; clone.NameTable = this.NameTable; clone.SerializationInfo = this.SerializationInfo; // IsBaseClass // Indicates that the serialization call is being made to // automatically serialize a base class. This needs to be // cleared at each level so that it isn't propagated to // the processing of the base class' properties so we don't // retain the value from the source args. // Succeeded // Success is determined at each level and shouldn't be // affected by caller state. This technically shouldn't // matter because the caller should have stopped processing // if an error occurred. return clone; }
/// <summary> /// Serializes an object /// </summary> /// <param name="writer">The target stream</param> /// <param name="instance">The object to serialize. This can be null.</param> /// <param name="flags">One or more <see cref="SerializedFlags"/> options</param> public static void Serialize <T>(IPrimitiveWriter writer, T instance, SerializerFlags flags) { TypeSerializationInfo typeInfo = TypeSerializationInfo.GetTypeInfo <T>(instance); TypeSerializationArgs args = new TypeSerializationArgs(); args.Writer = writer; args.Flags = flags; typeInfo.Serialize(instance, args); }
bool DeserializeCustomSerializable(ref object instance, TypeSerializationArgs args) { if (instance == null) { instance = CreateInstance(); } ICustomSerializable ics = instance as ICustomSerializable; ics.Deserialize(args.Reader); return(true); }
void SerializeCustomSerializable(object instance, TypeSerializationArgs args) { if (instance == null) { throw new ArgumentNullException("Cannot serialize null object with ICustomSerializable"); } else { ICustomSerializable ics = instance as ICustomSerializable; ics.Serialize(args.Writer); } }
void SerializeVersionSerializable(object instance, TypeSerializationArgs args) { if (instance == null) { args.Writer.Write(NullVersion); } else { IVersionSerializable ivs = instance as IVersionSerializable; args.Writer.Write((byte)ivs.CurrentVersion); ivs.Serialize(args.Writer); } }
public static object Deserialize(Stream stream, SerializerFlags flags, CompressionImplementation compression, Type instanceType) { TypeSerializationInfo typeInfo = null; TypeSerializationArgs args = new TypeSerializationArgs(); object instance = Activator.CreateInstance(instanceType); args.Flags = flags; args.Reader = GetReader(stream, flags, compression); typeInfo = TypeSerializationInfo.GetTypeInfo(instanceType); typeInfo.Deserialize(ref instance, args); return(instance); }
bool DeserializeVersionSerializable(ref object instance, TypeSerializationArgs args) { byte version = args.Reader.ReadByte(); bool success = false; if (version != NullVersion) { if (instance == null) { instance = CreateInstance(); } IVersionSerializable ivs = instance as IVersionSerializable; args.Reader.Response = SerializationResponse.Success; try { ivs.Deserialize(args.Reader, version); } catch (Exception exc) { const bool indicateTruncate = true; string data = Algorithm.ToByteString(args.Reader.BaseStream, 2 << 11, indicateTruncate); throw new SerializationException(string.Format("Failed to deserialized type {0} version {1} data {2}", instance.GetType().FullName, version, data), exc); } success = true; //throw exception if necessary switch (args.Reader.Response) { case SerializationResponse.Handled: throw new HandledVersionException(ivs.CurrentVersion, version); case SerializationResponse.Unhandled: throw new UnhandledVersionException(ivs.CurrentVersion, version); default: break; } } else { instance = null; } return(success); }
/// <summary> /// Internal use only /// </summary> /// <typeparam name="T"></typeparam> /// <param name="instance"></param> /// <param name="args"></param> public static void Serialize <T>(T instance, TypeSerializationArgs args) { TypeSerializationInfo typeInfo = null; if (args.IsBaseClass) { // For base class handling, make sure we explicitly get the type // info for the template parameter typeInfo = TypeSerializationInfo.GetTypeInfo(typeof(T)); } else { // Otherwise use the default type detection typeInfo = TypeSerializationInfo.GetTypeInfo <T>(instance); } typeInfo.Serialize(instance, args); }
public bool Deserialize(ref object instance, TypeSerializationArgs args) { if (deserializeMethod == null) { lock (syncRoot) { if (deserializeMethod == null) { deferredInitializationAction(); deferredInitializationAction = null; } } } if (attribute != null && attribute.SuppressWarningExceptions) { using (Serializer.OpenSuppressAlertScope()) { return(this.deserializeMethod(ref instance, args)); } } return(this.deserializeMethod(ref instance, args)); }
/// <summary> /// Internal use only /// </summary> /// <typeparam name="T"></typeparam> /// <param name="instance"></param> /// <param name="args"></param> /// <returns></returns> public static bool Deserialize <T>(ref object instance, TypeSerializationArgs args) { TypeSerializationInfo typeInfo = null; // Check arguments if (args.Reader == null) { Debug.Fail("Input stream is null"); throw new ArgumentNullException("reader"); } if (args.IsBaseClass) { // For base class handling, make sure we explicitly get the type // info for the template parameter typeInfo = TypeSerializationInfo.GetTypeInfo(typeof(T)); } else { // Otherwise use the default type detection typeInfo = TypeSerializationInfo.GetTypeInfo <T>(instance); } return(typeInfo.Deserialize(ref instance, args)); }
void SerializeAutoSerializable(object instance, TypeSerializationArgs args) { TypeSerializationArgs callerArgs = args; args = args.Clone(); if (this.IsInline) { // Inline objects are serialized with only a 2-byte length prefix // No version info or anything else int length = 0; long lengthPosition = args.Writer.BaseStream.Position; long endPosition = -1; args.Writer.Write((byte)length); if (instance != null) { args.Header = new TypeSerializationHeader(); args.Header.DataVersion = 1; args.Header.DataMinVersion = 1; this.autoSerializeMethod(instance, args); endPosition = args.Writer.BaseStream.Position; length = (int)((endPosition - lengthPosition) - InlineHeaderSize); if (length > MaxInlineSize) { throw new NotSupportedException(string.Format( "Inline classes must be {0} bytes or less. Class {1} serialized to {2} bytes.", MaxInlineSize, instance.GetType().FullName, length )); } args.Writer.BaseStream.Position = lengthPosition; args.Writer.Write((byte)length); args.Writer.BaseStream.Position = endPosition; } } else if (instance == null) { args.Writer.Write(NullVersion); } else { args.Header = new TypeSerializationHeader(); args.Header.DataVersion = (byte)this.CurrentVersion; args.Header.DataMinVersion = (byte)this.MinVersion; // If min version is less than or equal legacy version then write // out legacy version + 1 as the min version in the data stream.This // is to prevent older class definitions from attempting to // deserialize the new data using IVersionSerializable if ((this.LegacyVersion > 0) && (this.LegacyVersion >= this.MinVersion)) { args.Header.DataMinVersion = (byte)(this.LegacyVersion + 1); } // If this isn't a base class invocation then make sure // SerializationInfo is initialized for the first time. // If it is a base class then get the base class info // from the parent's SerializationInfo if (callerArgs.IsBaseClass == false) { ISerializationInfo info = instance as ISerializationInfo; if (info != null) { args.SerializationInfo = info.SerializationInfo; } else { // SerializationInfo may not be null in this case // because this may be an object contained in a parent // class. We need to make sure the child object doesn't // use the serialization info from the container args.SerializationInfo = null; } } else if (args.SerializationInfo != null) { args.SerializationInfo = callerArgs.SerializationInfo.BaseClassInfo; } // Handled cached serialization info if original data // was newer than the class definition that deserialized it if ( (args.SerializationInfo != null) && (args.SerializationInfo.Version > this.CurrentVersion) ) { args.Header.DataVersion = (byte)args.SerializationInfo.Version; args.Header.DataMinVersion = (byte)args.SerializationInfo.MinVersion; } // Write a special version byte to indicate this serialized // data uses a header. Because this version is guaranteed to // be higher than actual object versions, older serialization // code will simply treat this is a higher unhandled version, // which is true. args.Writer.Write(HasHeaderVersion); // Write the header with placeholder data args.Header.Write(args.Writer); // Serialize the object this.autoSerializeMethod(instance, args); // Update the header with final data. Note that the // TypeSerializationHeader class takes care of the // stream position args.Header.Write(args.Writer); } }
bool DeserializeUnknownType(ref object instance, TypeSerializationArgs args) { instance = args.Reader.Read(); return(true); }
void SerializeUnknownType(object instance, TypeSerializationArgs args) { args.Writer.Write(instance); }
bool DeserializeAutoSerializable(ref object instance, TypeSerializationArgs args) { byte dataVersion = 1; bool isSerializationInfoSupported = (instance == null) ? this.supportsSerializationInfo : (instance is ISerializationInfo); TypeSerializationArgs callerArgs = args; byte dataMinVersion = 0; // Create a local copy of args so we don't mess with caller's context args = args.Clone(); if (this.IsInline) { // Read length prefix. If length is 0 then object is null byte length = args.Reader.ReadByte(); if (length == 0) { dataVersion = NullVersion; } } else { dataVersion = args.Reader.ReadByte(); } if (dataVersion == NullVersion) { instance = null; return(false); } if (dataVersion == HasHeaderVersion) { args.Header = new TypeSerializationHeader(); args.Header.Read(args.Reader); dataVersion = args.Header.DataVersion; dataMinVersion = args.Header.DataMinVersion; } if ( // Version of the data is less than our supported minimum version // OR data is a lower version than the min version that can be deserialized // OR data is a higher version but this type isn't forward compatible // OR data has a min version that is higher than this current type definition (dataVersion < this.MinVersion) || (this.CurrentVersion < dataMinVersion) || (dataVersion < this.MinDeserializeVersion) || ((dataVersion > this.CurrentVersion) && (isSerializationInfoSupported == false)) || ((args.Header != null) && (args.Header.DataMinVersion > this.CurrentVersion)) ) { throw new UnhandledVersionException(this.CurrentVersion, dataVersion); } else { if (instance == null) { instance = CreateInstance(); } // If this is the derived class then create a new top-level // serialization info. If this is the base class then set // the base class serialization info if (callerArgs.IsBaseClass == false) { args.SerializationInfo = new SerializationInfo(); if (isSerializationInfoSupported == true) { ((ISerializationInfo)instance).SerializationInfo = args.SerializationInfo; } } else { callerArgs.SerializationInfo.BaseClassInfo = new SerializationInfo(); args.SerializationInfo = callerArgs.SerializationInfo.BaseClassInfo; } args.SerializationInfo.Version = dataVersion; if (args.Header != null) { args.SerializationInfo.MinVersion = args.Header.DataMinVersion; } this.autoDeserializeMethod(instance, dataVersion, args); if (args.Succeeded == false) { //this should never be hit, as it is a legacy of the volatile flag return(false); } if (isSerializationInfoSupported == true) { if (dataVersion > this.CurrentVersion) { int readDataLength = (int)(args.Reader.BaseStream.Position - args.Header.DataPosition); int unhandledDataLength = args.Header.DataLength - readDataLength; args.SerializationInfo.UnhandledData = args.Reader.ReadBytes(unhandledDataLength); } } } return(true); }