4 // Lluis Sanchez Gual (lluis@ideary.com)
6 // (C) 2003 Lluis Sanchez Gual
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
34 using System.Runtime.Serialization;
35 using System.Runtime.Remoting.Messaging;
36 using System.Reflection;
37 using System.Globalization;
39 namespace System.Runtime.Serialization.Formatters.Binary
41 abstract class TypeMetadata
43 public string TypeAssemblyName;
44 public string InstanceTypeName;
46 public abstract void WriteAssemblies (ObjectWriter ow, BinaryWriter writer);
47 public abstract void WriteTypeData (ObjectWriter ow, BinaryWriter writer, bool writeTypes);
48 public abstract void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data);
50 public virtual bool IsCompatible (TypeMetadata other)
56 public void BindToName (string assemblyName, string typeName)
58 if (assemblyName != null)
59 TypeAssemblyName = assemblyName;
61 InstanceTypeName = typeName;
65 public abstract bool RequiresTypes { get; }
68 abstract class ClrTypeMetadata: TypeMetadata
70 public Type InstanceType;
72 public ClrTypeMetadata (Type instanceType)
74 InstanceType = instanceType;
75 InstanceTypeName = instanceType.FullName;
76 TypeAssemblyName = instanceType.Assembly.FullName;
79 public override bool RequiresTypes {
84 class SerializableTypeMetadata: TypeMetadata
89 public SerializableTypeMetadata (Type itype, SerializationInfo info)
91 types = new Type [info.MemberCount];
92 names = new string [info.MemberCount];
94 SerializationInfoEnumerator e = info.GetEnumerator ();
99 types[n] = e.ObjectType;
104 TypeAssemblyName = info.AssemblyName;
105 InstanceTypeName = info.FullTypeName;
108 public override bool IsCompatible (TypeMetadata other)
110 if (!(other is SerializableTypeMetadata)) return false;
112 SerializableTypeMetadata tm = (SerializableTypeMetadata)other;
113 if (types.Length != tm.types.Length) return false;
114 if (TypeAssemblyName != tm.TypeAssemblyName) return false;
115 if (InstanceTypeName != tm.InstanceTypeName) return false;
116 for (int n=0; n<types.Length; n++)
118 if (types[n] != tm.types[n]) return false;
119 if (names[n] != tm.names[n]) return false;
124 public override void WriteAssemblies (ObjectWriter ow, BinaryWriter writer)
126 foreach (Type mtype in types)
130 type = type.GetElementType();
132 ow.WriteAssembly (writer, type.Assembly);
136 public override void WriteTypeData (ObjectWriter ow, BinaryWriter writer, bool writeTypes)
138 writer.Write (types.Length);
141 foreach (string name in names)
145 foreach (Type type in types)
146 ObjectWriter.WriteTypeCode (writer, type);
148 // Type specs of fields
149 foreach (Type type in types)
150 ow.WriteTypeSpec (writer, type);
153 public override void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data)
155 SerializationInfo info = (SerializationInfo) data;
156 SerializationInfoEnumerator e = info.GetEnumerator ();
158 while (e.MoveNext ())
159 ow.WriteValue (writer, e.ObjectType, e.Value);
162 public override bool RequiresTypes {
167 class MemberTypeMetadata: ClrTypeMetadata
169 MemberInfo[] members;
171 public MemberTypeMetadata (Type type, StreamingContext context): base (type)
173 members = FormatterServices.GetSerializableMembers (type, context);
176 public override void WriteAssemblies (ObjectWriter ow, BinaryWriter writer)
178 foreach (FieldInfo field in members)
180 Type type = field.FieldType;
182 type = type.GetElementType();
184 ow.WriteAssembly (writer, type.Assembly);
188 public override void WriteTypeData (ObjectWriter ow, BinaryWriter writer, bool writeTypes)
190 writer.Write (members.Length);
193 foreach (FieldInfo field in members)
194 writer.Write (field.Name);
198 foreach (FieldInfo field in members)
199 ObjectWriter.WriteTypeCode (writer, field.FieldType);
201 // Type specs of fields
202 foreach (FieldInfo field in members)
203 ow.WriteTypeSpec (writer, field.FieldType);
207 public override void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data)
209 object[] values = FormatterServices.GetObjectData (data, members);
210 for (int n=0; n<values.Length; n++)
211 ow.WriteValue (writer, ((FieldInfo)members[n]).FieldType, values[n]);
215 internal class ObjectWriter
217 ObjectIDGenerator _idGenerator = new ObjectIDGenerator();
218 Hashtable _cachedMetadata = new Hashtable();
219 Queue _pendingObjects = new Queue();
220 Hashtable _assemblyCache = new Hashtable();
222 // Type metadata that can be shared with all serializers
223 static Hashtable _cachedTypes = new Hashtable();
225 internal static Assembly CorlibAssembly = typeof(string).Assembly;
226 internal static string CorlibAssemblyName = typeof(string).Assembly.FullName;
228 ISurrogateSelector _surrogateSelector;
229 StreamingContext _context;
230 FormatterAssemblyStyle _assemblyFormat;
231 FormatterTypeStyle _typeFormat;
233 SerializationBinder _binder;
236 int ArrayBufferLength = 4096;
237 SerializationObjectManager _manager;
239 class MetadataReference
241 public TypeMetadata Metadata;
242 public long ObjectID;
244 public MetadataReference (TypeMetadata metadata, long id)
251 public ObjectWriter (BinaryFormatter formatter)
253 _surrogateSelector = formatter.SurrogateSelector;
254 _context = formatter.Context;
255 _assemblyFormat = formatter.AssemblyFormat;
256 _typeFormat = formatter.TypeFormat;
257 _manager = new SerializationObjectManager (formatter.Context);
259 _binder = formatter.Binder;
263 public void WriteObjectGraph (BinaryWriter writer, object obj, Header[] headers)
265 _pendingObjects.Clear();
266 if (headers != null) QueueObject (headers);
268 WriteQueuedObjects (writer);
269 WriteSerializationEnd (writer);
270 _manager.RaiseOnSerializedEvent ();
273 public void QueueObject (object obj)
275 _pendingObjects.Enqueue (obj);
278 public void WriteQueuedObjects (BinaryWriter writer)
280 while (_pendingObjects.Count > 0)
281 WriteObjectInstance (writer, _pendingObjects.Dequeue(), false);
284 public void WriteObjectInstance (BinaryWriter writer, object obj, bool isValueObject)
289 // If the object is a value type (not boxed) then there is no need
290 // to register it in the id generator, because it won't have other
293 if (isValueObject) id = _idGenerator.NextId;
294 else id = _idGenerator.GetId (obj, out firstTime);
297 WriteString (writer, id, (string)obj);
299 else if (obj is Array) {
300 WriteArray (writer, id, (Array)obj);
303 WriteObject (writer, id, obj);
306 public static void WriteSerializationEnd (BinaryWriter writer)
308 writer.Write ((byte) BinaryElement.End);
311 private void WriteObject (BinaryWriter writer, long id, object obj)
314 TypeMetadata metadata;
316 GetObjectData (obj, out metadata, out data);
317 MetadataReference metadataReference = (MetadataReference)_cachedMetadata [metadata.InstanceTypeName];
319 if (metadataReference != null && metadata.IsCompatible (metadataReference.Metadata))
321 // An object of the same type has already been serialized
322 // It is not necessary to write again type metadata
324 writer.Write ((byte) BinaryElement.RefTypeObject);
325 writer.Write ((int)id);
327 writer.Write ((int)metadataReference.ObjectID);
328 metadata.WriteObjectData (this, writer, data);
332 if (metadataReference == null)
334 metadataReference = new MetadataReference (metadata, id);
335 _cachedMetadata [metadata.InstanceTypeName] = metadataReference;
338 bool writeTypes = metadata.RequiresTypes || _typeFormat == FormatterTypeStyle.TypesAlways;
340 BinaryElement objectTag;
343 if (metadata.TypeAssemblyName == CorlibAssemblyName)
346 objectTag = writeTypes ? BinaryElement.RuntimeObject : BinaryElement.UntypedRuntimeObject;
351 objectTag = writeTypes ? BinaryElement.ExternalObject : BinaryElement.UntypedExternalObject;
352 assemblyId = WriteAssemblyName (writer, metadata.TypeAssemblyName);
355 // Registers the assemblies needed for each field
356 // If there are assemblies that where not registered before this object,
359 metadata.WriteAssemblies (this, writer);
363 writer.Write ((byte) objectTag);
364 writer.Write ((int)id);
365 writer.Write (metadata.InstanceTypeName);
367 metadata.WriteTypeData (this, writer, writeTypes);
368 if (assemblyId != -1) writer.Write (assemblyId);
370 metadata.WriteObjectData (this, writer, data);
373 private void GetObjectData (object obj, out TypeMetadata metadata, out object data)
375 Type instanceType = obj.GetType();
377 string binderAssemblyName = null;
378 string binderTypeName = null;
380 _binder.BindToName (instanceType, out binderAssemblyName, out binderTypeName);
382 // Check if the formatter has a surrogate selector, if it does,
383 // check if the surrogate selector handles objects of the given type.
385 if (_surrogateSelector != null)
387 ISurrogateSelector selector;
388 ISerializationSurrogate surrogate = _surrogateSelector.GetSurrogate (instanceType, _context, out selector);
389 if (surrogate != null)
391 SerializationInfo info = new SerializationInfo (instanceType, new FormatterConverter ());
392 surrogate.GetObjectData (obj, info, _context);
393 metadata = new SerializableTypeMetadata (instanceType, info);
396 metadata.BindToName (binderAssemblyName, binderTypeName);
404 // Check if the object is marked with the Serializable attribute
406 BinaryCommon.CheckSerializable (instanceType, _surrogateSelector, _context);
408 _manager.RegisterObject (obj);
410 ISerializable ser = obj as ISerializable;
414 SerializationInfo info = new SerializationInfo (instanceType, new FormatterConverter ());
415 ser.GetObjectData (info, _context);
416 metadata = new SerializableTypeMetadata (instanceType, info);
419 metadata.BindToName (binderAssemblyName, binderTypeName);
427 if (_context.Context != null)
429 // Don't cache metadata info when the Context property is not null sice
430 // we can't control the number of possible contexts in this case
431 metadata = new MemberTypeMetadata (instanceType, _context);
434 metadata.BindToName (binderAssemblyName, binderTypeName);
440 Hashtable typesTable;
442 lock (_cachedTypes) {
443 typesTable = (Hashtable) _cachedTypes [_context.State];
444 if (typesTable == null) {
445 typesTable = new Hashtable ();
446 _cachedTypes [_context.State] = typesTable;
454 metadata = (TypeMetadata) typesTable [instanceType];
457 if (metadata == null) {
458 metadata = CreateMemberTypeMetadata (instanceType);
461 metadata.BindToName (binderAssemblyName, binderTypeName);
465 typesTable [instanceType] = metadata;
470 TypeMetadata CreateMemberTypeMetadata (Type type)
472 if (!BinaryCommon.UseReflectionSerialization) {
473 Type metaType = CodeGenerator.GenerateMetadataType (type, _context);
474 return (TypeMetadata) Activator.CreateInstance (metaType);
477 return new MemberTypeMetadata (type, _context);
480 private void WriteArray (BinaryWriter writer, long id, Array array)
482 // There are 4 ways of serializing arrays:
483 // The element GenericArray (7) can be used for all arrays.
484 // The element ArrayOfPrimitiveType (15) can be used for single-dimensional
485 // arrays of primitive types
486 // The element ArrayOfObject (16) can be used for single-dimensional Object arrays
487 // The element ArrayOfString (17) can be used for single-dimensional string arrays
489 Type elementType = array.GetType().GetElementType();
491 if (elementType == typeof (object) && array.Rank == 1) {
492 WriteObjectArray (writer, id, array);
494 else if (elementType == typeof (string) && array.Rank == 1) {
495 WriteStringArray (writer, id, array);
497 else if (BinaryCommon.IsPrimitive(elementType) && array.Rank == 1) {
498 WritePrimitiveTypeArray (writer, id, array);
501 WriteGenericArray (writer, id, array);
504 private void WriteGenericArray (BinaryWriter writer, long id, Array array)
506 Type elementType = array.GetType().GetElementType();
508 // Registers and writes the assembly of the array element type if needed
510 var tag = GetTypeTag (elementType);
511 if ((tag != TypeTag.ArrayOfObject) && (tag != TypeTag.ArrayOfString) && (tag != TypeTag.ArrayOfPrimitiveType))
512 WriteAssembly (writer, elementType.Assembly);
516 writer.Write ((byte) BinaryElement.GenericArray);
517 writer.Write ((int)id);
519 // Write the structure of the array
521 if (elementType.IsArray)
522 writer.Write ((byte) ArrayStructure.Jagged);
523 else if (array.Rank == 1)
524 writer.Write ((byte) ArrayStructure.SingleDimensional);
526 writer.Write ((byte) ArrayStructure.MultiDimensional);
528 // Write the number of dimensions and the length
531 writer.Write (array.Rank);
532 for (int n=0; n<array.Rank; n++)
533 writer.Write (array.GetUpperBound (n) + 1);
536 WriteTypeCode (writer, elementType);
537 WriteTypeSpec (writer, elementType);
539 // Writes the values. For single-dimension array, a special tag is used
540 // to represent multiple consecutive null values. I don't know why this
541 // optimization is not used for multidimensional arrays.
543 if (array.Rank == 1 && !elementType.IsValueType)
545 WriteSingleDimensionArrayElements (writer, array, elementType);
549 foreach (object item in array)
550 WriteValue (writer, elementType, item);
554 private void WriteObjectArray (BinaryWriter writer, long id, Array array)
556 writer.Write ((byte) BinaryElement.ArrayOfObject);
557 writer.Write ((int)id);
558 writer.Write (array.Length); // Single dimension. Just write the length
559 WriteSingleDimensionArrayElements (writer, array, typeof (object));
562 private void WriteStringArray (BinaryWriter writer, long id, Array array)
564 writer.Write ((byte) BinaryElement.ArrayOfString);
565 writer.Write ((int)id);
566 writer.Write (array.Length); // Single dimension. Just write the length
567 WriteSingleDimensionArrayElements (writer, array, typeof (string));
570 private void WritePrimitiveTypeArray (BinaryWriter writer, long id, Array array)
572 writer.Write ((byte) BinaryElement.ArrayOfPrimitiveType);
573 writer.Write ((int)id);
574 writer.Write (array.Length); // Single dimension. Just write the length
576 Type elementType = array.GetType().GetElementType();
577 WriteTypeSpec (writer, elementType);
579 switch (Type.GetTypeCode (elementType))
581 case TypeCode.Boolean:
582 foreach (bool item in (bool[]) array)
587 writer.Write ((byte[]) array);
591 writer.Write ((char[]) array);
594 case TypeCode.DateTime:
595 foreach (DateTime item in (DateTime[]) array)
596 writer.Write (item.ToBinary ());
599 case TypeCode.Decimal:
600 foreach (decimal item in (decimal[]) array)
604 case TypeCode.Double:
605 if (array.Length > 2)
606 BlockWrite (writer, array, 8);
608 foreach (double item in (double[]) array)
613 if (array.Length > 2)
614 BlockWrite (writer, array, 2);
616 foreach (short item in (short[]) array)
621 if (array.Length > 2)
622 BlockWrite (writer, array, 4);
624 foreach (int item in (int[]) array)
629 if (array.Length > 2)
630 BlockWrite (writer, array, 8);
632 foreach (long item in (long[]) array)
637 if (array.Length > 2)
638 BlockWrite (writer, array, 1);
640 foreach (sbyte item in (sbyte[]) array)
644 case TypeCode.Single:
645 if (array.Length > 2)
646 BlockWrite (writer, array, 4);
648 foreach (float item in (float[]) array)
652 case TypeCode.UInt16:
653 if (array.Length > 2)
654 BlockWrite (writer, array, 2);
656 foreach (ushort item in (ushort[]) array)
660 case TypeCode.UInt32:
661 if (array.Length > 2)
662 BlockWrite (writer, array, 4);
664 foreach (uint item in (uint[]) array)
668 case TypeCode.UInt64:
669 if (array.Length > 2)
670 BlockWrite (writer, array, 8);
672 foreach (ulong item in (ulong[]) array)
676 case TypeCode.String:
677 foreach (string item in (string[]) array)
682 if (elementType == typeof (TimeSpan)) {
683 foreach (TimeSpan item in (TimeSpan[]) array)
684 writer.Write (item.Ticks);
687 throw new NotSupportedException ("Unsupported primitive type: " + elementType.FullName);
692 private void BlockWrite (BinaryWriter writer, Array array, int dataSize)
694 int totalSize = Buffer.ByteLength (array);
696 if (arrayBuffer == null || (totalSize > arrayBuffer.Length && arrayBuffer.Length != ArrayBufferLength))
697 arrayBuffer = new byte [totalSize <= ArrayBufferLength ? totalSize : ArrayBufferLength];
700 while (totalSize > 0) {
701 int size = totalSize < arrayBuffer.Length ? totalSize : arrayBuffer.Length;
702 Buffer.BlockCopy (array, pos, arrayBuffer, 0, size);
704 if (!BitConverter.IsLittleEndian && dataSize > 1)
705 BinaryCommon.SwapBytes (arrayBuffer, size, dataSize);
707 writer.Write (arrayBuffer, 0, size);
713 private void WriteSingleDimensionArrayElements (BinaryWriter writer, Array array, Type elementType)
716 foreach (object val in array)
718 if (val != null && numNulls > 0)
720 WriteNullFiller (writer, numNulls);
721 WriteValue (writer, elementType, val);
724 else if (val == null)
727 WriteValue (writer, elementType, val);
730 WriteNullFiller (writer, numNulls);
733 private void WriteNullFiller (BinaryWriter writer, int numNulls)
736 writer.Write ((byte) BinaryElement.NullValue);
738 else if (numNulls == 2) {
739 writer.Write ((byte) BinaryElement.NullValue);
740 writer.Write ((byte) BinaryElement.NullValue);
742 else if (numNulls <= byte.MaxValue) {
743 writer.Write ((byte) BinaryElement.ArrayFiller8b);
744 writer.Write ((byte) numNulls);
747 writer.Write ((byte) BinaryElement.ArrayFiller32b);
748 writer.Write (numNulls);
752 private void WriteObjectReference (BinaryWriter writer, long id)
755 writer.Write ((byte) BinaryElement.ObjectReference);
756 writer.Write ((int)id);
759 public void WriteValue (BinaryWriter writer, Type valueType, object val)
763 BinaryCommon.CheckSerializable (valueType, _surrogateSelector, _context);
764 writer.Write ((byte) BinaryElement.NullValue);
766 else if (BinaryCommon.IsPrimitive(val.GetType()))
768 if (!BinaryCommon.IsPrimitive(valueType))
770 // It is a boxed primitive type value
771 writer.Write ((byte) BinaryElement.BoxedPrimitiveTypeValue);
772 WriteTypeSpec (writer, val.GetType());
774 WritePrimitiveValue (writer, val);
776 else if (valueType.IsValueType)
778 // Value types are written embedded in the containing object
779 WriteObjectInstance (writer, val, true);
781 else if (val is string)
783 // Strings are written embedded, unless already registered
785 long id = _idGenerator.GetId (val, out firstTime);
787 if (firstTime) WriteObjectInstance (writer, val, false);
788 else WriteObjectReference (writer, id);
792 // It is a reference type. Write a forward reference and queue the
793 // object to the pending object list (unless already written).
796 long id = _idGenerator.GetId (val, out firstTime);
798 if (firstTime) _pendingObjects.Enqueue (val);
799 WriteObjectReference (writer, id);
803 private void WriteString (BinaryWriter writer, long id, string str)
805 writer.Write ((byte) BinaryElement.String);
806 writer.Write ((int)id);
810 public int WriteAssembly (BinaryWriter writer, Assembly assembly)
812 return WriteAssemblyName (writer, assembly.FullName);
815 public int WriteAssemblyName (BinaryWriter writer, string assembly)
817 if (assembly == ObjectWriter.CorlibAssemblyName) return -1;
820 int id = RegisterAssembly (assembly, out firstTime);
821 if (!firstTime) return id;
823 writer.Write ((byte) BinaryElement.Assembly);
825 if (_assemblyFormat == FormatterAssemblyStyle.Full)
826 writer.Write (assembly);
828 int i = assembly.IndexOf (',');
829 if (i != -1) assembly = assembly.Substring (0, i);
830 writer.Write (assembly);
836 public int GetAssemblyId (Assembly assembly)
838 return GetAssemblyNameId (assembly.FullName);
841 public int GetAssemblyNameId (string assembly)
843 return (int)_assemblyCache[assembly];
846 private int RegisterAssembly (string assembly, out bool firstTime)
848 if (_assemblyCache.ContainsKey (assembly))
851 return (int)_assemblyCache[assembly];
855 int id = (int)_idGenerator.GetId (0, out firstTime);
856 _assemblyCache.Add (assembly, id);
861 public static void WritePrimitiveValue (BinaryWriter writer, object value)
863 Type type = value.GetType();
865 switch (Type.GetTypeCode (type))
867 case TypeCode.Boolean:
868 writer.Write ((bool)value);
872 writer.Write ((byte) value);
876 writer.Write ((char) value);
879 case TypeCode.DateTime:
880 writer.Write ( ((DateTime)value).ToBinary ());
883 case TypeCode.Decimal:
884 writer.Write (((decimal) value).ToString (CultureInfo.InvariantCulture));
887 case TypeCode.Double:
888 writer.Write ((double) value);
892 writer.Write ((short) value);
896 writer.Write ((int) value);
900 writer.Write ((long) value);
904 writer.Write ((sbyte) value);
907 case TypeCode.Single:
908 writer.Write ((float) value);
911 case TypeCode.UInt16:
912 writer.Write ((ushort) value);
915 case TypeCode.UInt32:
916 writer.Write ((uint) value);
919 case TypeCode.UInt64:
920 writer.Write ((ulong) value);
923 case TypeCode.String:
924 writer.Write ((string) value);
928 if (type == typeof (TimeSpan))
929 writer.Write (((TimeSpan)value).Ticks);
931 throw new NotSupportedException ("Unsupported primitive type: " + value.GetType().FullName);
936 public static void WriteTypeCode (BinaryWriter writer, Type type)
938 writer.Write ((byte) GetTypeTag (type));
941 public static TypeTag GetTypeTag (Type type)
943 if (type == typeof (string)) {
944 return TypeTag.String;
946 else if (BinaryCommon.IsPrimitive (type)) {
947 return TypeTag.PrimitiveType;
949 else if (type == typeof (object)) {
950 return TypeTag.ObjectType;
952 else if (type.IsArray && type.GetArrayRank() == 1 && type.GetElementType() == typeof (object)) {
953 return TypeTag.ArrayOfObject;
955 else if (type.IsArray && type.GetArrayRank() == 1 && type.GetElementType() == typeof (string)){
956 return TypeTag.ArrayOfString;
958 else if (type.IsArray && type.GetArrayRank() == 1 && BinaryCommon.IsPrimitive(type.GetElementType())) {
959 return TypeTag.ArrayOfPrimitiveType;
961 else if (type.Assembly == CorlibAssembly) {
962 return TypeTag.RuntimeType;
965 return TypeTag.GenericType;
968 public void WriteTypeSpec (BinaryWriter writer, Type type)
970 // WARNING Keep in sync with EmitWriteTypeSpec
972 switch (GetTypeTag (type))
974 case TypeTag.PrimitiveType:
975 writer.Write (BinaryCommon.GetTypeCode (type));
978 case TypeTag.RuntimeType:
979 string fullName = type.FullName;
980 // Map System.MonoType to MS.NET's System.RuntimeType,
981 // when called in remoting context.
982 // Note that this code does not need to be in sync with
983 // EmitWriteTypeSpec because serializing a MethodCall
984 // won't trigger the CodeGenerator.
985 if (_context.State == StreamingContextStates.Remoting)
986 if (type == typeof (System.MonoType))
987 fullName = "System.RuntimeType";
988 else if (type == typeof (System.MonoType[]))
989 fullName = "System.RuntimeType[]";
990 writer.Write (fullName);
993 case TypeTag.GenericType:
994 writer.Write (type.FullName);
995 writer.Write ((int)GetAssemblyId (type.Assembly));
998 case TypeTag.ArrayOfPrimitiveType:
999 writer.Write (BinaryCommon.GetTypeCode (type.GetElementType()));
1003 // Type spec not needed