public static void GetObjectData(DObject/*!*/ instance, SerializationInfo/*!*/ info, StreamingContext strctx) { info.SetType(typeof(Deserializer)); SerializationContext context = SerializationContext.CreateFromStreamingContext(strctx); bool sleep_called; PhpArray sleep_result; // try to get the caches __sleep result if (context.SleepResults.TryGetValue(instance, out sleep_result)) { if (Object.ReferenceEquals(sleep_result, SerializationContext.NoSleepResultSingleton)) { sleep_called = false; sleep_result = null; } else sleep_called = true; } else { sleep_result = instance.Sleep(context.ClassContext, context.ScriptContext, out sleep_called); context.SleepResults.Add(instance, (sleep_called ? sleep_result : SerializationContext.NoSleepResultSingleton)); } if (sleep_called && sleep_result == null) { // __sleep did not return an array -> this instance will deserialize as NULL info.AddValue(__PHP_Incomplete_Class.ClassNameFieldName, String.Empty); } else { // if we have a sleep result, serialize fields according to it, otherwise serialize all fields IEnumerable<KeyValuePair<string, object>> serializable_properties; object real_object = null; if (sleep_result == null) { serializable_properties = Serialization.EnumerateSerializableProperties( instance, true); // get PHP fields only // serialize CLR real object in the "CLR way" if (!(instance is PhpObject)) real_object = instance.RealObject; } else { serializable_properties = Serialization.EnumerateSerializableProperties( instance, sleep_result, context.ScriptContext); } bool type_name_serialized = false; bool real_object_serialized = false; foreach (KeyValuePair<string, object> pair in serializable_properties) { if (pair.Key == __PHP_Incomplete_Class.ClassNameFieldName) type_name_serialized = true; if (pair.Key == ClrRealObjectSerializationInfoKey) { // unwrap the possibly wrapped CLR real object info.AddValue(pair.Key, PhpVariable.Unwrap(pair.Value)); real_object_serialized = true; } else { PhpReference reference = pair.Value as PhpReference; info.AddValue(pair.Key, WrapPropertyValue(pair.Value)); } } // if the type name has not been serialized, do it now if (!type_name_serialized) info.AddValue(__PHP_Incomplete_Class.ClassNameFieldName, instance.TypeName); // if the real object has not been serialized, do it now if (!real_object_serialized) info.AddValue(ClrRealObjectSerializationInfoKey, real_object); } }
/// <summary> /// Serializes <see cref="DObject"/> using PHP serialization. /// </summary> /// <param name="value">The object.</param> private void WritePhpObjectInternal(DObject/*!*/value) { byte[] binaryClassName; // determine class name bool avoid_pic_name = false; string class_name = null; __PHP_Incomplete_Class pic = value as __PHP_Incomplete_Class; if (pic != null) { if (pic.__PHP_Incomplete_Class_Name.IsSet) { avoid_pic_name = true; class_name = pic.__PHP_Incomplete_Class_Name.Value as string; } } if (value is stdClass) class_name = stdClass.ClassName; if (class_name == null) class_name = value.TypeName; // is the instance PHP5.1 Serializable? if (value.RealObject is Library.SPL.Serializable) { context.Stack.AddFrame(); object res = PhpVariable.Dereference(value.InvokeMethod("serialize", null, context)); if (res == null) { // serialize returned NULL -> serialize the instance as NULL WriteNull(); return; } byte[] resdata = null; if (res is PhpString) { res = res.ToString(); } if (res is string) { resdata = writer.Encoding.GetBytes((string)res); } else if (res is PhpBytes) { resdata = ((PhpBytes)res).ReadonlyData; } if (resdata == null) { // serialize did not return NULL nor a string -> throw an exception SPL.Exception.ThrowSplException( _ctx => new SPL.Exception(_ctx, true), context, string.Format(CoreResources.serialize_must_return_null_or_string, value.TypeName), 0, null); } writer.Write(Tokens.ObjectSer); writer.Write(Tokens.Colon); binaryClassName = writer.Encoding.GetBytes(class_name); // write out class name writer.Write(binaryClassName.Length); writer.Write(Tokens.Colon); writer.Write(Tokens.Quote); // flush the StreamWriter before accessing its underlying stream writer.Flush(); writer.BaseStream.Write(binaryClassName, 0, binaryClassName.Length); writer.Write(Tokens.Quote); writer.Write(Tokens.Colon); // write out the result of serialize writer.Write(resdata.Length); writer.Write(Tokens.Colon); writer.Write(Tokens.BraceOpen); // flush the StreamWriter before accessing its underlying stream writer.Flush(); writer.BaseStream.Write(resdata, 0, resdata.Length); writer.Write(Tokens.BraceClose); return; } // try to call the __sleep method bool sleep_called; PhpArray ser_props = value.Sleep(ClassContext, context, out sleep_called); if (sleep_called && ser_props == null) { // __sleep did not return an array -> serialize the instance as NULL WriteNull(); return; } writer.Write(Tokens.Object); writer.Write(Tokens.Colon); // write out class name binaryClassName = writer.Encoding.GetBytes(class_name); // write out class name writer.Write(binaryClassName.Length); writer.Write(Tokens.Colon); writer.Write(Tokens.Quote); // flush the StreamWriter before accessing its underlying stream writer.Flush(); writer.BaseStream.Write(binaryClassName, 0, binaryClassName.Length); writer.Write(Tokens.Quote); writer.Write(Tokens.Colon); // write out property count if (ser_props != null) writer.Write(ser_props.Count); else writer.Write(value.Count - (avoid_pic_name ? 1 : 0)); writer.Write(Tokens.Colon); writer.Write(Tokens.BraceOpen); // write out properties if (ser_props != null) WriteSleepResult(value, ser_props); else WriteAllProperties(value, avoid_pic_name); writer.Write(Tokens.BraceClose); }
public static void GetObjectData(DObject /*!*/ instance, SerializationInfo /*!*/ info, StreamingContext strctx) { info.SetType(typeof(Deserializer)); SerializationContext context = SerializationContext.CreateFromStreamingContext(strctx); bool sleep_called; PhpArray sleep_result; // try to get the caches __sleep result if (context.SleepResults.TryGetValue(instance, out sleep_result)) { if (Object.ReferenceEquals(sleep_result, SerializationContext.NoSleepResultSingleton)) { sleep_called = false; sleep_result = null; } else { sleep_called = true; } } else { sleep_result = instance.Sleep(context.ClassContext, context.ScriptContext, out sleep_called); context.SleepResults.Add(instance, (sleep_called ? sleep_result : SerializationContext.NoSleepResultSingleton)); } if (sleep_called && sleep_result == null) { // __sleep did not return an array -> this instance will deserialize as NULL info.AddValue(__PHP_Incomplete_Class.ClassNameFieldName, String.Empty); } else { // if we have a sleep result, serialize fields according to it, otherwise serialize all fields IEnumerable <KeyValuePair <string, object> > serializable_properties; object real_object = null; if (sleep_result == null) { serializable_properties = Serialization.EnumerateSerializableProperties( instance, true); // get PHP fields only // serialize CLR real object in the "CLR way" if (!(instance is PhpObject)) { real_object = instance.RealObject; } } else { serializable_properties = Serialization.EnumerateSerializableProperties( instance, sleep_result, context.ScriptContext); } bool type_name_serialized = false; bool real_object_serialized = false; foreach (KeyValuePair <string, object> pair in serializable_properties) { if (pair.Key == __PHP_Incomplete_Class.ClassNameFieldName) { type_name_serialized = true; } if (pair.Key == ClrRealObjectSerializationInfoKey) { // unwrap the possibly wrapped CLR real object info.AddValue(pair.Key, PhpVariable.Unwrap(pair.Value)); real_object_serialized = true; } else { PhpReference reference = pair.Value as PhpReference; info.AddValue(pair.Key, WrapPropertyValue(pair.Value)); } } // if the type name has not been serialized, do it now if (!type_name_serialized) { info.AddValue(__PHP_Incomplete_Class.ClassNameFieldName, instance.TypeName); } // if the real object has not been serialized, do it now if (!real_object_serialized) { info.AddValue(ClrRealObjectSerializationInfoKey, real_object); } } }