-// ObjectWriter.cs
-//
-// Author:
-// Lluis Sanchez Gual (lsg@ctv.es)
-//
-// (C) 2003 Lluis Sanchez Gual
-\r
-// FIXME: Implement the missing binary elements\r
+// ObjectWriter.cs\r
+//\r
+// Author:\r
+// Lluis Sanchez Gual (lluis@ideary.com)\r
+//\r
+// (C) 2003 Lluis Sanchez Gual\r
\r
using System;\r
using System.IO;\r
using System.Collections;\r
using System.Runtime.Serialization;\r
+using System.Runtime.Remoting.Messaging;\r
using System.Reflection;\r
+using System.Globalization;\r
\r
namespace System.Runtime.Serialization.Formatters.Binary\r
{\r
+ abstract class TypeMetadata\r
+ {\r
+ public TypeMetadata (Type instanceType)\r
+ {\r
+ InstanceType = instanceType;\r
+ TypeAssembly = instanceType.Assembly;\r
+ }\r
+ \r
+ public Assembly TypeAssembly;\r
+ public Type InstanceType;\r
+ \r
+ public abstract void WriteAssemblies (ObjectWriter ow, BinaryWriter writer);\r
+ public abstract void WriteTypeData (ObjectWriter ow, BinaryWriter writer);\r
+ public abstract void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data);\r
+ \r
+ public virtual bool IsCompatible (TypeMetadata other)\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+ \r
+ class SerializableTypeMetadata: TypeMetadata\r
+ {\r
+ Type[] types;\r
+ string[] names;\r
+ \r
+ public SerializableTypeMetadata (Type itype, SerializationInfo info): base (itype)\r
+ {\r
+ types = new Type [info.MemberCount];\r
+ names = new string [info.MemberCount];\r
+\r
+ SerializationInfoEnumerator e = info.GetEnumerator ();\r
+\r
+ int n = 0;\r
+ while (e.MoveNext ())\r
+ {\r
+ types[n] = e.ObjectType;\r
+ names[n] = e.Name;\r
+ n++;\r
+ }\r
+\r
+ if (info.FullTypeName != InstanceType.FullName || info.AssemblyName != TypeAssembly.FullName) \r
+ {\r
+ TypeAssembly = Assembly.Load (info.AssemblyName);\r
+ InstanceType = TypeAssembly.GetType (info.FullTypeName);\r
+ }\r
+ }\r
+ \r
+ public override bool IsCompatible (TypeMetadata other)\r
+ {\r
+ if (!(other is SerializableTypeMetadata)) return false;\r
+ \r
+ SerializableTypeMetadata tm = (SerializableTypeMetadata)other;\r
+ if (types.Length != tm.types.Length) return false;\r
+ if (TypeAssembly != tm.TypeAssembly) return false;\r
+ if (InstanceType != tm.InstanceType) return false;\r
+ for (int n=0; n<types.Length; n++)\r
+ {\r
+ if (types[n] != tm.types[n]) return false;\r
+ if (names[n] != tm.names[n]) return false;\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ public override void WriteAssemblies (ObjectWriter ow, BinaryWriter writer)\r
+ {\r
+ foreach (Type mtype in types)\r
+ {\r
+ Type type = mtype;\r
+ while (type.IsArray) \r
+ type = type.GetElementType();\r
+ \r
+ ow.WriteAssembly (writer, type.Assembly);\r
+ }\r
+ }\r
+ \r
+ public override void WriteTypeData (ObjectWriter ow, BinaryWriter writer)\r
+ {\r
+ writer.Write (types.Length);\r
+\r
+ // Names of fields\r
+ foreach (string name in names)\r
+ writer.Write (name);\r
+\r
+ // Types of fields\r
+ foreach (Type type in types)\r
+ ObjectWriter.WriteTypeCode (writer, type);\r
+\r
+ // Type specs of fields\r
+ foreach (Type type in types)\r
+ ow.WriteTypeSpec (writer, type);\r
+ }\r
+ \r
+ public override void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data)\r
+ {\r
+ SerializationInfo info = (SerializationInfo) data;\r
+ SerializationInfoEnumerator e = info.GetEnumerator ();\r
+\r
+ while (e.MoveNext ())\r
+ ow.WriteValue (writer, e.ObjectType, e.Value);\r
+ }\r
+ }\r
+ \r
+ class MemberTypeMetadata: TypeMetadata\r
+ {\r
+ MemberInfo[] members;\r
+ \r
+ public MemberTypeMetadata (Type type, StreamingContext context): base (type)\r
+ {\r
+ members = FormatterServices.GetSerializableMembers (type, context);\r
+ }\r
+\r
+ public override void WriteAssemblies (ObjectWriter ow, BinaryWriter writer)\r
+ {\r
+ foreach (FieldInfo field in members)\r
+ {\r
+ Type type = field.FieldType;\r
+ while (type.IsArray) \r
+ type = type.GetElementType();\r
+ \r
+ ow.WriteAssembly (writer, type.Assembly);\r
+ }\r
+ }\r
+ \r
+ public override void WriteTypeData (ObjectWriter ow, BinaryWriter writer)\r
+ {\r
+ writer.Write (members.Length);\r
+\r
+ // Names of fields\r
+ foreach (FieldInfo field in members) {\r
+ if (field.DeclaringType == InstanceType)\r
+ writer.Write (field.Name);\r
+ else\r
+ writer.Write (field.DeclaringType.Name + "+" + field.Name);\r
+ }\r
+\r
+ // Types of fields\r
+ foreach (FieldInfo field in members)\r
+ ObjectWriter.WriteTypeCode (writer, field.FieldType);\r
+\r
+ // Type specs of fields\r
+ foreach (FieldInfo field in members)\r
+ ow.WriteTypeSpec (writer, field.FieldType);\r
+ }\r
+ \r
+ public override void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data)\r
+ {\r
+ object[] values = FormatterServices.GetObjectData (data, members);\r
+ for (int n=0; n<values.Length; n++)\r
+ ow.WriteValue (writer, ((FieldInfo)members[n]).FieldType, values[n]);\r
+ }\r
+ }\r
+ \r
internal class ObjectWriter\r
{\r
ObjectIDGenerator _idGenerator = new ObjectIDGenerator();\r
- Hashtable _cachedTypes = new Hashtable();\r
+ Hashtable _cachedMetadata = new Hashtable();\r
Queue _pendingObjects = new Queue();\r
- Assembly _corlibAssembly;\r
Hashtable _assemblyCache = new Hashtable();\r
+ \r
+ // Type metadata that can be shared with all serializers\r
+ static Hashtable _cachedTypes = new Hashtable();\r
+\r
+ internal static Assembly CorlibAssembly = typeof(string).Assembly;\r
\r
ISurrogateSelector _surrogateSelector;\r
StreamingContext _context;\r
-\r
- class TypeMetadata\r
+ FormatterAssemblyStyle _assemblyFormat;\r
+ \r
+ class MetadataReference\r
{\r
- public Type[] Types;\r
- public string[] Names;\r
- public Assembly TypeAssembly;\r
- public Type InstanceType;\r
+ public TypeMetadata Metadata;\r
public long ObjectID;\r
- public bool CustomSerialization;\r
-\r
- public bool Equals (TypeMetadata other)\r
+ \r
+ public MetadataReference (TypeMetadata metadata, long id)\r
{\r
- if (!CustomSerialization) return true;\r
-\r
- TypeMetadata tm = (TypeMetadata)other;\r
- if (Types.Length != tm.Types.Length) return false;\r
- if (TypeAssembly != other.TypeAssembly) return false;\r
- if (InstanceType != other.InstanceType) return false;\r
- for (int n=0; n<Types.Length; n++)\r
- {\r
- if (Types[n] != tm.Types[n]) return false;\r
- if (Names[n] != tm.Names[n]) return false;\r
- }\r
- return true;\r
+ Metadata = metadata;\r
+ ObjectID = id;\r
}\r
}\r
-\r
- public ObjectWriter(ISurrogateSelector surrogateSelector, StreamingContext context)\r
+ \r
+ public ObjectWriter (ISurrogateSelector surrogateSelector, StreamingContext context, FormatterAssemblyStyle assemblyFormat)\r
{\r
_surrogateSelector = surrogateSelector;\r
_context = context;\r
- _corlibAssembly = GetType().Assembly;\r
+ _assemblyFormat = assemblyFormat;\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
+ if (obj is string) {\r
WriteString (writer, id, (string)obj);\r
}\r
- else if (obj.GetType().IsArray) {\r
+ else if (obj is Array) {\r
WriteArray (writer, id, (Array)obj);\r
}\r
else\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
+ object data;\r
TypeMetadata metadata;\r
\r
- GetObjectData (obj, out metadata, out values);\r
+ GetObjectData (obj, out metadata, out data);\r
+ MetadataReference metadataReference = (MetadataReference)_cachedMetadata [metadata.InstanceType];\r
\r
- TypeMetadata chachedMetadata = (TypeMetadata)_cachedTypes[metadata.InstanceType];\r
-\r
- if (chachedMetadata != null && metadata.Equals(chachedMetadata))\r
+ if (metadataReference != null && metadata.IsCompatible (metadataReference.Metadata))\r
{\r
// An object of the same type has already been serialized\r
// It is not necessary to write again type metadata\r
writer.Write ((byte) BinaryElement.RefTypeObject);\r
writer.Write ((int)id);\r
\r
- // Get the id of the object that has the same type as this\r
- long refId = chachedMetadata.ObjectID;\r
-\r
- writer.Write ((int)refId);\r
- WriteObjectContent (writer, metadata.Types, values);\r
+ writer.Write ((int)metadataReference.ObjectID);\r
+ metadata.WriteObjectData (this, writer, data);\r
return;\r
}\r
\r
- if (chachedMetadata == null)\r
+ if (metadataReference == null)\r
{\r
- metadata.ObjectID = id;\r
- _cachedTypes [metadata.InstanceType] = metadata;\r
+ metadataReference = new MetadataReference (metadata, id);\r
+ _cachedMetadata [metadata.InstanceType] = metadataReference;\r
}\r
\r
BinaryElement objectTag;\r
\r
int assemblyId;\r
- if (metadata.TypeAssembly == _corlibAssembly)\r
+ if (metadata.TypeAssembly == CorlibAssembly)\r
{\r
// A corlib type\r
objectTag = BinaryElement.RuntimeObject;\r
else\r
{\r
objectTag = BinaryElement.ExternalObject;\r
-\r
- bool firstTime;\r
- assemblyId = RegisterAssembly (metadata.TypeAssembly, out firstTime);\r
- if (firstTime) WriteAssembly (writer, assemblyId, metadata.TypeAssembly);\r
+ assemblyId = WriteAssembly (writer, metadata.TypeAssembly);\r
}\r
\r
// Registers the assemblies needed for each field\r
// If there are assemblies that where not registered before this object,\r
// write them now\r
\r
- foreach (object value in values)\r
- {\r
- if (value == null) continue;\r
-\r
- Type memberType = value.GetType();\r
- while (memberType.IsArray) \r
- memberType = memberType.GetElementType();\r
-\r
- if (memberType.Assembly != _corlibAssembly)\r
- {\r
- bool firstTime;\r
- int aid = RegisterAssembly (memberType.Assembly, out firstTime);\r
- if (firstTime) WriteAssembly (writer, aid, memberType.Assembly);\r
- }\r
- }\r
+ metadata.WriteAssemblies (this, writer);\r
\r
// Writes the object\r
\r
writer.Write ((byte) objectTag);\r
writer.Write ((int)id);\r
writer.Write (metadata.InstanceType.FullName);\r
- WriteObjectMetadata (writer, metadata, assemblyId);\r
- WriteObjectContent (writer, metadata.Types, values);\r
- }\r
-\r
- private void WriteObjectMetadata (BinaryWriter writer, TypeMetadata metadata, int assemblyId)\r
- {\r
- Type[] types = metadata.Types;\r
- string[] names = metadata.Names;\r
-\r
- writer.Write (types.Length);\r
-\r
- // Names of fields\r
- foreach (string name in names)\r
- writer.Write (name);\r
-\r
- // Types of fields\r
- foreach (Type type in types)\r
- WriteTypeCode (writer, type);\r
-\r
- // Type specs of fields\r
- foreach (Type type in types)\r
- WriteTypeSpec (writer, type);\r
-\r
+ \r
+ metadata.WriteTypeData (this, writer);\r
if (assemblyId != -1) writer.Write (assemblyId);\r
+ \r
+ metadata.WriteObjectData (this, writer, data);\r
}\r
\r
- private void WriteObjectContent (BinaryWriter writer, Type[] types, object[] values)\r
- {\r
- for (int n=0; n<values.Length; n++)\r
- WriteValue (writer, types[n], values[n]);\r
- }\r
-\r
- private void GetObjectData (object obj, out TypeMetadata metadata, out object[] values)\r
+ private void GetObjectData (object obj, out TypeMetadata metadata, out object data)\r
{\r
- metadata = new TypeMetadata();\r
- metadata.InstanceType = obj.GetType();\r
- metadata.TypeAssembly = metadata.InstanceType.Assembly;\r
+ Type instanceType = obj.GetType();\r
\r
// Check if the formatter has a surrogate selector \96 if it does, \r
// check if the surrogate selector handles objects of the given type. \r
if (_surrogateSelector != null)\r
{\r
ISurrogateSelector selector;\r
- ISerializationSurrogate surrogate = _surrogateSelector.GetSurrogate (metadata.InstanceType, _context, out selector);\r
+ ISerializationSurrogate surrogate = _surrogateSelector.GetSurrogate (instanceType, _context, out selector);\r
if (surrogate != null)\r
{\r
- SerializationInfo info = new SerializationInfo (metadata.InstanceType, new FormatterConverter ());\r
- surrogate.GetObjectData(obj, info, _context);\r
- GetDataFromSerializationInfo (info, ref metadata, out values);\r
+ SerializationInfo info = new SerializationInfo (instanceType, new FormatterConverter ());\r
+ surrogate.GetObjectData (obj, info, _context);\r
+ metadata = new SerializableTypeMetadata (instanceType, info);\r
+ data = info;\r
return;\r
}\r
}\r
\r
// Check if the object is marked with the Serializable attribute\r
\r
- if (!metadata.InstanceType.IsSerializable)\r
- throw new SerializationException ("Type " + metadata.InstanceType +
- " is not marked as Serializable " +
- "and does not implement ISerializable.");
+ if (!instanceType.IsSerializable)\r
+ throw new SerializationException ("Type " + instanceType +\r
+ " is not marked as Serializable " + \r
+ "and does not implement ISerializable.");\r
\r
ISerializable ser = obj as ISerializable;\r
\r
if (ser != null) \r
{\r
- SerializationInfo info = new SerializationInfo (metadata.InstanceType, new FormatterConverter ());\r
+ SerializationInfo info = new SerializationInfo (instanceType, new FormatterConverter ());\r
ser.GetObjectData (info, _context);\r
- GetDataFromSerializationInfo (info, ref metadata, out values);\r
+ metadata = new SerializableTypeMetadata (instanceType, info);\r
+ data = info;\r
} \r
else \r
- GetDataFromObjectFields (obj, ref metadata, out values);\r
- }\r
-\r
- private void GetDataFromSerializationInfo (SerializationInfo info, ref TypeMetadata metadata, out object[] values)\r
- {\r
- Type[] types = types = new Type [info.MemberCount];\r
- string[] names = new string [info.MemberCount];\r
- values = new object [info.MemberCount];\r
+ {\r
+ data = obj;\r
+ if (_context.Context != null)\r
+ {\r
+ // Don't cache metadata info when the Context property is not null sice\r
+ // we can't control the number of possible contexts in this case\r
+ metadata = new MemberTypeMetadata (instanceType, _context);\r
+ return;\r
+ }\r
+ \r
+ Hashtable typesTable;\r
+ bool isNew = false;\r
+ lock (_cachedTypes) {\r
+ typesTable = (Hashtable) _cachedTypes [_context.State];\r
+ if (typesTable == null) {\r
+ typesTable = new Hashtable ();\r
+ _cachedTypes [_context.State] = typesTable;\r
+ isNew = true;\r
+ }\r
+ }\r
\r
- SerializationInfoEnumerator e = info.GetEnumerator ();\r
+ metadata = null;\r
+ lock (typesTable) {\r
+ if (!isNew) {\r
+ metadata = (TypeMetadata) typesTable [instanceType];\r
+ }\r
\r
- int n = 0;\r
- while (e.MoveNext ())\r
- {\r
- values[n] = e.Value;\r
- types[n] = e.ObjectType;\r
- names[n] = e.Name;\r
- n++;\r
- }\r
+ if (metadata == null) {\r
+ metadata = CreateMemberTypeMetadata (instanceType);\r
+ }\r
\r
- if (info.FullTypeName != metadata.InstanceType.FullName || info.AssemblyName != metadata.TypeAssembly.FullName) \r
- {\r
- metadata.TypeAssembly = Assembly.Load (info.AssemblyName);\r
- metadata.InstanceType = metadata.TypeAssembly.GetType (info.FullTypeName);\r
+ typesTable [instanceType] = metadata;\r
+ }\r
}\r
-\r
- metadata.Types = types;\r
- metadata.Names = names;\r
- metadata.CustomSerialization = true;\r
}\r
-\r
- private void GetDataFromObjectFields (object obj, ref TypeMetadata metadata, out object[] values)\r
+ \r
+ TypeMetadata CreateMemberTypeMetadata (Type type)\r
{\r
- MemberInfo[] members = FormatterServices.GetSerializableMembers (obj.GetType(), _context);\r
- values = FormatterServices.GetObjectData (obj, members);\r
-\r
- Type[] types = new Type [members.Length];\r
- string[] names = new string [members.Length];\r
-\r
- for (int n=0; n<members.Length; n++)\r
- {\r
- MemberInfo member = members[n];\r
- names[n] = member.Name;\r
- if (member is FieldInfo)\r
- types[n] = ((FieldInfo)member).FieldType;\r
- else if (member is PropertyInfo)\r
- types[n] = ((PropertyInfo)member).PropertyType;\r
+ if (!BinaryCommon.UseReflectionSerialization) {\r
+ Type metaType = CodeGenerator.GenerateMetadataType (type, _context);\r
+ return (TypeMetadata) Activator.CreateInstance (metaType);\r
}\r
-\r
- metadata.Types = types;\r
- metadata.Names = names;\r
- metadata.CustomSerialization = false;\r
+ else\r
+ return new MemberTypeMetadata (type, _context);\r
}\r
\r
private void WriteArray (BinaryWriter writer, long id, Array array)\r
\r
// Registers and writes the assembly of the array element type if needed\r
\r
- if (!elementType.IsArray && elementType.Assembly != _corlibAssembly)\r
- {\r
- bool firstTime;\r
- int aid = RegisterAssembly (elementType.Assembly, out firstTime);\r
- if (firstTime) WriteAssembly (writer, aid, elementType.Assembly);\r
- }\r
+ if (!elementType.IsArray)\r
+ WriteAssembly (writer, elementType.Assembly);\r
\r
// Writes the array\r
\r
}\r
else\r
{\r
- int[] indices = new int[array.Rank];\r
-\r
- // Initialize indexes\r
- for (int dim = array.Rank-1; dim >= 0; dim--)\r
- indices[dim] = array.GetLowerBound (dim);\r
-\r
- bool end = false;\r
- while (!end)\r
- {\r
- WriteValue (writer, elementType, array.GetValue (indices));\r
-\r
- for (int dim = array.Rank-1; dim >= 0; dim--)\r
- {\r
- indices[dim]++;\r
- if (indices[dim] > array.GetUpperBound (dim))\r
- {\r
- if (dim > 0) {\r
- indices[dim] = array.GetLowerBound (dim);\r
- continue; // Increment the next dimension's index\r
- }\r
- end = true; // That was the last dimension. Finished.\r
- }\r
- break;\r
- }\r
- }\r
+ foreach (object item in array)\r
+ WriteValue (writer, elementType, item);\r
}\r
}\r
\r
Type elementType = array.GetType().GetElementType();\r
WriteTypeSpec (writer, elementType);\r
\r
- for (int n=0; n<array.Length; n++)\r
- WritePrimitiveValue (writer, array.GetValue (n));\r
+ switch (Type.GetTypeCode (elementType))\r
+ {\r
+ case TypeCode.Boolean:\r
+ foreach (bool item in (bool[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.Byte:\r
+ writer.Write ((byte[]) array);\r
+ break;\r
+\r
+ case TypeCode.Char:\r
+ foreach (char item in (char[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.DateTime: \r
+ foreach (DateTime item in (DateTime[]) array)\r
+ writer.Write (item.Ticks);\r
+ break;\r
+\r
+ case TypeCode.Decimal:\r
+ foreach (decimal item in (decimal[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.Double:\r
+ foreach (double item in (double[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.Int16:\r
+ foreach (short item in (short[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.Int32:\r
+ foreach (int item in (int[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.Int64:\r
+ foreach (long item in (long[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.SByte:\r
+ foreach (sbyte item in (sbyte[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.Single:\r
+ foreach (float item in (float[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.UInt16:\r
+ foreach (ushort item in (ushort[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.UInt32:\r
+ foreach (uint item in (uint[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.UInt64:\r
+ foreach (ulong item in (ulong[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ case TypeCode.String:\r
+ foreach (string item in (string[]) array)\r
+ writer.Write (item);\r
+ break;\r
+\r
+ default:\r
+ if (elementType == typeof (TimeSpan)) {\r
+ foreach (TimeSpan item in (TimeSpan[]) array)\r
+ writer.Write (item.Ticks);\r
+ }\r
+ else\r
+ throw new NotSupportedException ("Unsupported primitive type: " + elementType.FullName);\r
+ break;\r
+ } \r
}\r
\r
private void WriteSingleDimensionArrayElements (BinaryWriter writer, Array array, Type elementType)\r
{\r
int numNulls = 0;\r
- for (int n = array.GetLowerBound (0); n<=array.GetUpperBound(0); n++)\r
+ foreach (object val in array)\r
{\r
- object val = array.GetValue (n);\r
if (val != null && numNulls > 0)\r
{\r
WriteNullFiller (writer, numNulls);\r
\r
private void WriteObjectReference (BinaryWriter writer, long id)\r
{\r
+\r
writer.Write ((byte) BinaryElement.ObjectReference);\r
writer.Write ((int)id);\r
}\r
\r
- private void WriteValue (BinaryWriter writer, Type valueType, object val)\r
+ public void WriteValue (BinaryWriter writer, Type valueType, object val)\r
{\r
if (val == null) \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
+ else if (val is string)\r
{\r
// Strings are written embedded, unless already registered\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
writer.Write (str);\r
}\r
\r
- private void WriteAssembly (BinaryWriter writer, int id, Assembly assembly)\r
+ public int WriteAssembly (BinaryWriter writer, Assembly assembly)\r
{\r
+ if (assembly == ObjectWriter.CorlibAssembly) return -1;\r
+ \r
+ bool firstTime;\r
+ int id = RegisterAssembly (assembly, out firstTime);\r
+ if (!firstTime) return id;\r
+ \r
writer.Write ((byte) BinaryElement.Assembly);\r
writer.Write (id);\r
- writer.Write (assembly.GetName ().FullName);\r
+ if (_assemblyFormat == FormatterAssemblyStyle.Full)\r
+ writer.Write (assembly.GetName ().FullName);\r
+ else\r
+ writer.Write (assembly.GetName ().Name);\r
+ \r
+ return id;\r
}\r
\r
- private int GetAssemblyId (Assembly assembly)\r
+ public int GetAssemblyId (Assembly assembly)\r
{\r
return (int)_assemblyCache[assembly];\r
}\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
break;\r
\r
case TypeCode.Decimal:\r
- writer.Write ((decimal) value);\r
+ writer.Write (((decimal) value).ToString (CultureInfo.InvariantCulture));\r
break;\r
\r
case TypeCode.Double:\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
else if (type.IsArray && type.GetArrayRank() == 1 && BinaryCommon.IsPrimitive(type.GetElementType())) {\r
return TypeTag.ArrayOfPrimitiveType;\r
}\r
- else if (type.Assembly == _corlibAssembly) {\r
+ else if (type.Assembly == CorlibAssembly) {\r
return TypeTag.RuntimeType;\r
}\r
else\r
return TypeTag.GenericType;\r
}\r
\r
- private void WriteTypeSpec (BinaryWriter writer, Type type)\r
+ public void WriteTypeSpec (BinaryWriter writer, Type type)\r
{\r
+ // WARNING Keep in sync with EmitWriteTypeSpec\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