-// ObjectWriter.cs
-//
-// Author:
-// Lluis Sanchez Gual (lsg@ctv.es)
-//
-// (C) 2003 Lluis Sanchez Gual
+// ObjectWriter.cs\r
+//\r
+// Author:\r
+// Lluis Sanchez Gual (lluis@ideary.com)\r
+//\r
+// (C) 2003 Lluis Sanchez Gual\r
\r
// FIXME: Implement the missing binary elements\r
\r
using System.IO;\r
using System.Collections;\r
using System.Runtime.Serialization;\r
+using System.Runtime.Remoting.Messaging;\r
using System.Reflection;\r
\r
namespace System.Runtime.Serialization.Formatters.Binary\r
ObjectIDGenerator _idGenerator = new ObjectIDGenerator();\r
Hashtable _cachedTypes = new Hashtable();\r
Queue _pendingObjects = new Queue();\r
- Assembly _corlibAssembly;\r
Hashtable _assemblyCache = new Hashtable();\r
\r
+ static Assembly _corlibAssembly = typeof(string).Assembly;\r
+\r
ISurrogateSelector _surrogateSelector;\r
StreamingContext _context;\r
\r
{\r
_surrogateSelector = surrogateSelector;\r
_context = context;\r
- _corlibAssembly = GetType().Assembly;\r
}\r
\r
- public void WriteObjectGraph (BinaryWriter writer, object obj)\r
+ public void WriteObjectGraph (BinaryWriter writer, object obj, Header[] headers)\r
{\r
- writer.Write (BinaryCommon.BinaryHeader);\r
-\r
_pendingObjects.Clear();\r
+ if (headers != null) QueueObject (headers);\r
+ QueueObject (obj);\r
+ WriteQueuedObjects (writer);\r
+ WriteSerializationEnd (writer);\r
+ }\r
\r
- WriteObjectInstance (writer, obj);\r
+ public void QueueObject (object obj)\r
+ {\r
+ _pendingObjects.Enqueue (obj);\r
+ }\r
\r
- while (_pendingObjects.Count > 0)\r
- WriteObjectInstance (writer, _pendingObjects.Dequeue());\r
+ public void WriteQueuedObjects (BinaryWriter writer)\r
+ {\r
\r
- writer.Write ((byte) BinaryElement.End);\r
+ while (_pendingObjects.Count > 0)\r
+ WriteObjectInstance (writer, _pendingObjects.Dequeue(), false);\r
}\r
\r
- public void WriteObjectInstance (BinaryWriter writer, object obj)\r
+ public void WriteObjectInstance (BinaryWriter writer, object obj, bool isValueObject)\r
{\r
bool firstTime;\r
- long id = _idGenerator.GetId (obj, out firstTime);\r
+ long id;\r
+\r
+ // If the object is a value type (not boxed) then there is no need\r
+ // to register it in the id generator, because it won't have other\r
+ // references to it\r
+\r
+ if (isValueObject) id = _idGenerator.NextId;\r
+ else id = _idGenerator.GetId (obj, out firstTime);\r
\r
if (obj.GetType() == typeof(string)) {\r
WriteString (writer, id, (string)obj);\r
WriteObject (writer, id, obj);\r
}\r
\r
+ public static void WriteSerializationEnd (BinaryWriter writer)\r
+ {\r
+ writer.Write ((byte) BinaryElement.End);\r
+ }\r
+\r
private void WriteObject (BinaryWriter writer, long id, object obj)\r
{\r
object[] values;\r
// Check if the object is marked with the Serializable attribute\r
\r
if (!metadata.InstanceType.IsSerializable)\r
- throw new SerializationException("Serializable objects must be marked with the Serializable attribute");\r
+ throw new SerializationException ("Type " + metadata.InstanceType +\r
+ " is not marked as Serializable " + \r
+ "and does not implement ISerializable.");\r
\r
ISerializable ser = obj as ISerializable;\r
\r
\r
metadata.Types = types;\r
metadata.Names = names;\r
+\r
metadata.CustomSerialization = false;\r
}\r
\r
\r
private void WriteObjectReference (BinaryWriter writer, long id)\r
{\r
+\r
writer.Write ((byte) BinaryElement.ObjectReference);\r
writer.Write ((int)id);\r
}\r
else if (valueType.IsValueType)\r
{\r
// Value types are written embedded in the containing object\r
- WriteObjectInstance (writer, val);\r
+ WriteObjectInstance (writer, val, true);\r
}\r
else if (val.GetType() == typeof(string))\r
{\r
bool firstTime;\r
long id = _idGenerator.GetId (val, out firstTime);\r
\r
- if (firstTime) WriteObjectInstance (writer, val);\r
+ if (firstTime) WriteObjectInstance (writer, val, false);\r
else WriteObjectReference (writer, id);\r
} \r
else\r
}\r
}\r
\r
- private void WritePrimitiveValue (BinaryWriter writer, object value)\r
+ public static void WritePrimitiveValue (BinaryWriter writer, object value)\r
{\r
- switch (Type.GetTypeCode (value.GetType()))\r
+ Type type = value.GetType();\r
+\r
+ switch (Type.GetTypeCode (type))\r
{\r
case TypeCode.Boolean:\r
writer.Write ((bool)value);\r
case TypeCode.UInt64:\r
writer.Write ((ulong) value);\r
break;\r
+\r
+ case TypeCode.String:\r
+ writer.Write ((string) value);\r
+ break;\r
+\r
+ default:\r
+ if (type == typeof (TimeSpan))\r
+ writer.Write (((TimeSpan)value).Ticks);\r
+ else\r
+ throw new NotSupportedException ("Unsupported primitive type: " + value.GetType().FullName);\r
+ break;\r
}\r
}\r
\r
- private void WriteTypeCode (BinaryWriter writer, Type type)\r
+ public static void WriteTypeCode (BinaryWriter writer, Type type)\r
{\r
writer.Write ((byte) GetTypeTag (type));\r
}\r
\r
- private TypeTag GetTypeTag (Type type)\r
+ public static TypeTag GetTypeTag (Type type)\r
{\r
if (type == typeof (string)) {\r
return TypeTag.String;\r
return TypeTag.GenericType;\r
}\r
\r
- private void WriteTypeSpec (BinaryWriter writer, Type type)\r
+ public void WriteTypeSpec (BinaryWriter writer, Type type)\r
{\r
switch (GetTypeTag (type))\r
{\r
case TypeTag.PrimitiveType:\r
- writer.Write ((byte) (Type.GetTypeCode (type) - 1));\r
+ writer.Write (BinaryCommon.GetTypeCode (type));\r
break;\r
\r
case TypeTag.RuntimeType:\r
break;\r
\r
case TypeTag.ArrayOfPrimitiveType:\r
- writer.Write ((byte) (Type.GetTypeCode (type.GetElementType()) - 1));\r
+ writer.Write (BinaryCommon.GetTypeCode (type.GetElementType()));\r
break;\r
\r
default:\r