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;
38 using System.Runtime.CompilerServices;
40 namespace System.Runtime.Serialization.Formatters.Binary
43 public class GetForwardedAttribute
45 public static string GetAssemblyName (Type self)
47 var attrs = self.GetCustomAttributes(
48 typeof (TypeForwardedFromAttribute), false);
49 if (attrs.Length == 0)
50 return self.Assembly.FullName;
52 return ((TypeForwardedFromAttribute)attrs [0]).AssemblyFullName;
57 abstract class TypeMetadata
59 public string TypeAssemblyName;
60 public string InstanceTypeName;
62 public abstract void WriteAssemblies (ObjectWriter ow, BinaryWriter writer);
63 public abstract void WriteTypeData (ObjectWriter ow, BinaryWriter writer, bool writeTypes);
64 public abstract void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data);
66 public virtual bool IsCompatible (TypeMetadata other)
72 public void BindToName (string assemblyName, string typeName)
74 if (assemblyName != null)
75 TypeAssemblyName = assemblyName;
77 InstanceTypeName = typeName;
81 public abstract bool RequiresTypes { get; }
84 abstract class ClrTypeMetadata: TypeMetadata
86 public Type InstanceType;
88 public ClrTypeMetadata (Type instanceType)
90 InstanceType = instanceType;
91 InstanceTypeName = instanceType.FullName;
93 TypeAssemblyName = GetForwardedAttribute.GetAssemblyName(instanceType);
95 TypeAssemblyName = instanceType.Assembly.FullName;
99 public override bool RequiresTypes {
100 get { return false; }
104 class SerializableTypeMetadata: TypeMetadata
109 public SerializableTypeMetadata (Type itype, SerializationInfo info)
111 types = new Type [info.MemberCount];
112 names = new string [info.MemberCount];
114 SerializationInfoEnumerator e = info.GetEnumerator ();
117 while (e.MoveNext ())
119 types[n] = e.ObjectType;
124 TypeAssemblyName = info.AssemblyName;
126 InstanceTypeName = GetForwardedAttribute.GetAssemblyName(itype);
128 InstanceTypeName = info.FullTypeName;
132 public override bool IsCompatible (TypeMetadata other)
134 if (!(other is SerializableTypeMetadata)) return false;
136 SerializableTypeMetadata tm = (SerializableTypeMetadata)other;
137 if (types.Length != tm.types.Length) return false;
138 if (TypeAssemblyName != tm.TypeAssemblyName) return false;
139 if (InstanceTypeName != tm.InstanceTypeName) return false;
140 for (int n=0; n<types.Length; n++)
142 if (types[n] != tm.types[n]) return false;
143 if (names[n] != tm.names[n]) return false;
148 public override void WriteAssemblies (ObjectWriter ow, BinaryWriter writer)
150 foreach (Type mtype in types)
154 type = type.GetElementType();
156 ow.WriteTypeAssembly (writer, type);
160 public override void WriteTypeData (ObjectWriter ow, BinaryWriter writer, bool writeTypes)
162 writer.Write (types.Length);
165 foreach (string name in names)
169 foreach (Type type in types)
170 ObjectWriter.WriteTypeCode (writer, type);
172 // Type specs of fields
173 foreach (Type type in types)
174 ow.WriteTypeSpec (writer, type);
177 public override void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data)
179 SerializationInfo info = (SerializationInfo) data;
180 SerializationInfoEnumerator e = info.GetEnumerator ();
182 while (e.MoveNext ())
183 ow.WriteValue (writer, e.ObjectType, e.Value);
186 public override bool RequiresTypes {
191 class MemberTypeMetadata: ClrTypeMetadata
193 MemberInfo[] members;
195 public MemberTypeMetadata (Type type, StreamingContext context): base (type)
197 members = FormatterServices.GetSerializableMembers (type, context);
200 public override void WriteAssemblies (ObjectWriter ow, BinaryWriter writer)
202 foreach (FieldInfo field in members)
204 Type type = field.FieldType;
206 type = type.GetElementType();
208 ow.WriteTypeAssembly (writer, type);
212 public override void WriteTypeData (ObjectWriter ow, BinaryWriter writer, bool writeTypes)
214 writer.Write (members.Length);
217 foreach (FieldInfo field in members)
218 writer.Write (field.Name);
222 foreach (FieldInfo field in members)
223 ObjectWriter.WriteTypeCode (writer, field.FieldType);
225 // Type specs of fields
226 foreach (FieldInfo field in members)
227 ow.WriteTypeSpec (writer, field.FieldType);
231 public override void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data)
233 object[] values = FormatterServices.GetObjectData (data, members);
234 for (int n=0; n<values.Length; n++)
235 ow.WriteValue (writer, ((FieldInfo)members[n]).FieldType, values[n]);
239 internal class ObjectWriter
241 ObjectIDGenerator _idGenerator = new ObjectIDGenerator();
242 Hashtable _cachedMetadata = new Hashtable();
243 Queue _pendingObjects = new Queue();
244 Hashtable _assemblyCache = new Hashtable();
246 // Type metadata that can be shared with all serializers
247 static Hashtable _cachedTypes = new Hashtable();
249 internal static Assembly CorlibAssembly = typeof(string).Assembly;
250 internal static string CorlibAssemblyName = typeof(string).Assembly.FullName;
252 ISurrogateSelector _surrogateSelector;
253 StreamingContext _context;
254 FormatterAssemblyStyle _assemblyFormat;
255 FormatterTypeStyle _typeFormat;
257 SerializationBinder _binder;
260 int ArrayBufferLength = 4096;
261 SerializationObjectManager _manager;
263 class MetadataReference
265 public TypeMetadata Metadata;
266 public long ObjectID;
268 public MetadataReference (TypeMetadata metadata, long id)
275 public ObjectWriter (BinaryFormatter formatter)
277 _surrogateSelector = formatter.SurrogateSelector;
278 _context = formatter.Context;
279 _assemblyFormat = formatter.AssemblyFormat;
280 _typeFormat = formatter.TypeFormat;
281 _manager = new SerializationObjectManager (formatter.Context);
283 _binder = formatter.Binder;
287 public void WriteObjectGraph (BinaryWriter writer, object obj, Header[] headers)
289 _pendingObjects.Clear();
290 if (headers != null) QueueObject (headers);
292 WriteQueuedObjects (writer);
293 WriteSerializationEnd (writer);
294 _manager.RaiseOnSerializedEvent ();
297 public void QueueObject (object obj)
299 _pendingObjects.Enqueue (obj);
302 public void WriteQueuedObjects (BinaryWriter writer)
304 while (_pendingObjects.Count > 0)
305 WriteObjectInstance (writer, _pendingObjects.Dequeue(), false);
308 public void WriteObjectInstance (BinaryWriter writer, object obj, bool isValueObject)
313 // If the object is a value type (not boxed) then there is no need
314 // to register it in the id generator, because it won't have other
317 if (isValueObject) id = _idGenerator.NextId;
318 else id = _idGenerator.GetId (obj, out firstTime);
321 WriteString (writer, id, (string)obj);
323 else if (obj is Array) {
324 WriteArray (writer, id, (Array)obj);
327 WriteObject (writer, id, obj);
330 public static void WriteSerializationEnd (BinaryWriter writer)
332 writer.Write ((byte) BinaryElement.End);
335 private void WriteObject (BinaryWriter writer, long id, object obj)
338 TypeMetadata metadata;
340 GetObjectData (obj, out metadata, out data);
341 MetadataReference metadataReference = (MetadataReference)_cachedMetadata [metadata.InstanceTypeName];
343 if (metadataReference != null && metadata.IsCompatible (metadataReference.Metadata))
345 // An object of the same type has already been serialized
346 // It is not necessary to write again type metadata
348 writer.Write ((byte) BinaryElement.RefTypeObject);
349 writer.Write ((int)id);
351 writer.Write ((int)metadataReference.ObjectID);
352 metadata.WriteObjectData (this, writer, data);
356 if (metadataReference == null)
358 metadataReference = new MetadataReference (metadata, id);
359 _cachedMetadata [metadata.InstanceTypeName] = metadataReference;
362 bool writeTypes = metadata.RequiresTypes || _typeFormat == FormatterTypeStyle.TypesAlways;
364 BinaryElement objectTag;
367 if (metadata.TypeAssemblyName == CorlibAssemblyName)
370 objectTag = writeTypes ? BinaryElement.RuntimeObject : BinaryElement.UntypedRuntimeObject;
375 objectTag = writeTypes ? BinaryElement.ExternalObject : BinaryElement.UntypedExternalObject;
376 assemblyId = WriteAssemblyName (writer, metadata.TypeAssemblyName);
379 // Registers the assemblies needed for each field
380 // If there are assemblies that where not registered before this object,
383 metadata.WriteAssemblies (this, writer);
387 writer.Write ((byte) objectTag);
388 writer.Write ((int)id);
389 writer.Write (metadata.InstanceTypeName);
391 metadata.WriteTypeData (this, writer, writeTypes);
392 if (assemblyId != -1) writer.Write (assemblyId);
394 metadata.WriteObjectData (this, writer, data);
397 private void GetObjectData (object obj, out TypeMetadata metadata, out object data)
399 Type instanceType = obj.GetType();
401 string binderAssemblyName = null;
402 string binderTypeName = null;
404 _binder.BindToName (instanceType, out binderAssemblyName, out binderTypeName);
406 // Check if the formatter has a surrogate selector, if it does,
407 // check if the surrogate selector handles objects of the given type.
409 if (_surrogateSelector != null)
411 ISurrogateSelector selector;
412 ISerializationSurrogate surrogate = _surrogateSelector.GetSurrogate (instanceType, _context, out selector);
413 if (surrogate != null)
415 SerializationInfo info = new SerializationInfo (instanceType, new FormatterConverter ());
416 surrogate.GetObjectData (obj, info, _context);
417 metadata = new SerializableTypeMetadata (instanceType, info);
420 metadata.BindToName (binderAssemblyName, binderTypeName);
428 // Check if the object is marked with the Serializable attribute
430 BinaryCommon.CheckSerializable (instanceType, _surrogateSelector, _context);
432 _manager.RegisterObject (obj);
434 ISerializable ser = obj as ISerializable;
438 SerializationInfo info = new SerializationInfo (instanceType, new FormatterConverter ());
439 ser.GetObjectData (info, _context);
440 metadata = new SerializableTypeMetadata (instanceType, info);
443 metadata.BindToName (binderAssemblyName, binderTypeName);
451 if (_context.Context != null)
453 // Don't cache metadata info when the Context property is not null sice
454 // we can't control the number of possible contexts in this case
455 metadata = new MemberTypeMetadata (instanceType, _context);
458 metadata.BindToName (binderAssemblyName, binderTypeName);
464 Hashtable typesTable;
466 lock (_cachedTypes) {
467 typesTable = (Hashtable) _cachedTypes [_context.State];
468 if (typesTable == null) {
469 typesTable = new Hashtable ();
470 _cachedTypes [_context.State] = typesTable;
478 metadata = (TypeMetadata) typesTable [instanceType];
481 if (metadata == null) {
482 metadata = CreateMemberTypeMetadata (instanceType);
485 metadata.BindToName (binderAssemblyName, binderTypeName);
489 typesTable [instanceType] = metadata;
494 TypeMetadata CreateMemberTypeMetadata (Type type)
496 #if !FULL_AOT_RUNTIME
497 if (!BinaryCommon.UseReflectionSerialization) {
498 Type metaType = CodeGenerator.GenerateMetadataType (type, _context);
499 return (TypeMetadata) Activator.CreateInstance (metaType);
503 return new MemberTypeMetadata (type, _context);
506 private void WriteArray (BinaryWriter writer, long id, Array array)
508 // There are 4 ways of serializing arrays:
509 // The element GenericArray (7) can be used for all arrays.
510 // The element ArrayOfPrimitiveType (15) can be used for single-dimensional
511 // arrays of primitive types
512 // The element ArrayOfObject (16) can be used for single-dimensional Object arrays
513 // The element ArrayOfString (17) can be used for single-dimensional string arrays
515 Type elementType = array.GetType().GetElementType();
517 if (elementType == typeof (object) && array.Rank == 1) {
518 WriteObjectArray (writer, id, array);
520 else if (elementType == typeof (string) && array.Rank == 1) {
521 WriteStringArray (writer, id, array);
523 else if (BinaryCommon.IsPrimitive(elementType) && array.Rank == 1) {
524 WritePrimitiveTypeArray (writer, id, array);
527 WriteGenericArray (writer, id, array);
530 private void WriteGenericArray (BinaryWriter writer, long id, Array array)
532 Type elementType = array.GetType().GetElementType();
534 // Registers and writes the assembly of the array element type if needed
536 var tag = GetTypeTag (elementType);
537 if ((tag != TypeTag.ArrayOfObject) && (tag != TypeTag.ArrayOfString) && (tag != TypeTag.ArrayOfPrimitiveType))
538 WriteTypeAssembly (writer, elementType);
542 writer.Write ((byte) BinaryElement.GenericArray);
543 writer.Write ((int)id);
545 // Write the structure of the array
547 if (elementType.IsArray)
548 writer.Write ((byte) ArrayStructure.Jagged);
549 else if (array.Rank == 1)
550 writer.Write ((byte) ArrayStructure.SingleDimensional);
552 writer.Write ((byte) ArrayStructure.MultiDimensional);
554 // Write the number of dimensions and the length
557 writer.Write (array.Rank);
558 for (int n=0; n<array.Rank; n++)
559 writer.Write (array.GetUpperBound (n) + 1);
562 WriteTypeCode (writer, elementType);
563 WriteTypeSpec (writer, elementType);
565 // Writes the values. For single-dimension array, a special tag is used
566 // to represent multiple consecutive null values. I don't know why this
567 // optimization is not used for multidimensional arrays.
569 if (array.Rank == 1 && !elementType.IsValueType)
571 WriteSingleDimensionArrayElements (writer, array, elementType);
575 foreach (object item in array)
576 WriteValue (writer, elementType, item);
580 private void WriteObjectArray (BinaryWriter writer, long id, Array array)
582 writer.Write ((byte) BinaryElement.ArrayOfObject);
583 writer.Write ((int)id);
584 writer.Write (array.Length); // Single dimension. Just write the length
585 WriteSingleDimensionArrayElements (writer, array, typeof (object));
588 private void WriteStringArray (BinaryWriter writer, long id, Array array)
590 writer.Write ((byte) BinaryElement.ArrayOfString);
591 writer.Write ((int)id);
592 writer.Write (array.Length); // Single dimension. Just write the length
593 WriteSingleDimensionArrayElements (writer, array, typeof (string));
596 private void WritePrimitiveTypeArray (BinaryWriter writer, long id, Array array)
598 writer.Write ((byte) BinaryElement.ArrayOfPrimitiveType);
599 writer.Write ((int)id);
600 writer.Write (array.Length); // Single dimension. Just write the length
602 Type elementType = array.GetType().GetElementType();
603 WriteTypeSpec (writer, elementType);
605 switch (Type.GetTypeCode (elementType))
607 case TypeCode.Boolean:
608 foreach (bool item in (bool[]) array)
613 writer.Write ((byte[]) array);
617 writer.Write ((char[]) array);
620 case TypeCode.DateTime:
621 foreach (DateTime item in (DateTime[]) array)
622 writer.Write (item.ToBinary ());
625 case TypeCode.Decimal:
626 foreach (decimal item in (decimal[]) array)
630 case TypeCode.Double:
631 if (array.Length > 2)
632 BlockWrite (writer, array, 8);
634 foreach (double item in (double[]) array)
639 if (array.Length > 2)
640 BlockWrite (writer, array, 2);
642 foreach (short item in (short[]) array)
647 if (array.Length > 2)
648 BlockWrite (writer, array, 4);
650 foreach (int item in (int[]) array)
655 if (array.Length > 2)
656 BlockWrite (writer, array, 8);
658 foreach (long item in (long[]) array)
663 if (array.Length > 2)
664 BlockWrite (writer, array, 1);
666 foreach (sbyte item in (sbyte[]) array)
670 case TypeCode.Single:
671 if (array.Length > 2)
672 BlockWrite (writer, array, 4);
674 foreach (float item in (float[]) array)
678 case TypeCode.UInt16:
679 if (array.Length > 2)
680 BlockWrite (writer, array, 2);
682 foreach (ushort item in (ushort[]) array)
686 case TypeCode.UInt32:
687 if (array.Length > 2)
688 BlockWrite (writer, array, 4);
690 foreach (uint item in (uint[]) array)
694 case TypeCode.UInt64:
695 if (array.Length > 2)
696 BlockWrite (writer, array, 8);
698 foreach (ulong item in (ulong[]) array)
702 case TypeCode.String:
703 foreach (string item in (string[]) array)
708 if (elementType == typeof (TimeSpan)) {
709 foreach (TimeSpan item in (TimeSpan[]) array)
710 writer.Write (item.Ticks);
713 throw new NotSupportedException ("Unsupported primitive type: " + elementType.FullName);
718 private void BlockWrite (BinaryWriter writer, Array array, int dataSize)
720 int totalSize = Buffer.ByteLength (array);
722 if (arrayBuffer == null || (totalSize > arrayBuffer.Length && arrayBuffer.Length != ArrayBufferLength))
723 arrayBuffer = new byte [totalSize <= ArrayBufferLength ? totalSize : ArrayBufferLength];
726 while (totalSize > 0) {
727 int size = totalSize < arrayBuffer.Length ? totalSize : arrayBuffer.Length;
728 Buffer.BlockCopy (array, pos, arrayBuffer, 0, size);
730 if (!BitConverter.IsLittleEndian && dataSize > 1)
731 BinaryCommon.SwapBytes (arrayBuffer, size, dataSize);
733 writer.Write (arrayBuffer, 0, size);
739 private void WriteSingleDimensionArrayElements (BinaryWriter writer, Array array, Type elementType)
742 foreach (object val in array)
744 if (val != null && numNulls > 0)
746 WriteNullFiller (writer, numNulls);
747 WriteValue (writer, elementType, val);
750 else if (val == null)
753 WriteValue (writer, elementType, val);
756 WriteNullFiller (writer, numNulls);
759 private void WriteNullFiller (BinaryWriter writer, int numNulls)
762 writer.Write ((byte) BinaryElement.NullValue);
764 else if (numNulls == 2) {
765 writer.Write ((byte) BinaryElement.NullValue);
766 writer.Write ((byte) BinaryElement.NullValue);
768 else if (numNulls <= byte.MaxValue) {
769 writer.Write ((byte) BinaryElement.ArrayFiller8b);
770 writer.Write ((byte) numNulls);
773 writer.Write ((byte) BinaryElement.ArrayFiller32b);
774 writer.Write (numNulls);
778 private void WriteObjectReference (BinaryWriter writer, long id)
781 writer.Write ((byte) BinaryElement.ObjectReference);
782 writer.Write ((int)id);
785 public void WriteValue (BinaryWriter writer, Type valueType, object val)
789 BinaryCommon.CheckSerializable (valueType, _surrogateSelector, _context);
790 writer.Write ((byte) BinaryElement.NullValue);
792 else if (BinaryCommon.IsPrimitive(val.GetType()))
794 if (!BinaryCommon.IsPrimitive(valueType))
796 // It is a boxed primitive type value
797 writer.Write ((byte) BinaryElement.BoxedPrimitiveTypeValue);
798 WriteTypeSpec (writer, val.GetType());
800 WritePrimitiveValue (writer, val);
802 else if (valueType.IsValueType)
804 // Value types are written embedded in the containing object
805 WriteObjectInstance (writer, val, true);
807 else if (val is string)
809 // Strings are written embedded, unless already registered
811 long id = _idGenerator.GetId (val, out firstTime);
813 if (firstTime) WriteObjectInstance (writer, val, false);
814 else WriteObjectReference (writer, id);
818 // It is a reference type. Write a forward reference and queue the
819 // object to the pending object list (unless already written).
822 long id = _idGenerator.GetId (val, out firstTime);
824 if (firstTime) _pendingObjects.Enqueue (val);
825 WriteObjectReference (writer, id);
829 private void WriteString (BinaryWriter writer, long id, string str)
831 writer.Write ((byte) BinaryElement.String);
832 writer.Write ((int)id);
836 public int WriteTypeAssembly (BinaryWriter writer, Type aType)
839 return WriteAssemblyName (writer, GetForwardedAttribute.GetAssemblyName(aType));
841 return WriteAssemblyName (writer, aType.Assembly.FullName);
845 public int WriteAssembly (BinaryWriter writer, Assembly assembly)
847 return WriteAssemblyName (writer, assembly.FullName);
850 public int WriteAssemblyName (BinaryWriter writer, string assembly)
852 if (assembly == ObjectWriter.CorlibAssemblyName) return -1;
855 int id = RegisterAssembly (assembly, out firstTime);
856 if (!firstTime) return id;
858 writer.Write ((byte) BinaryElement.Assembly);
860 if (_assemblyFormat == FormatterAssemblyStyle.Full)
861 writer.Write (assembly);
863 int i = assembly.IndexOf (',');
864 if (i != -1) assembly = assembly.Substring (0, i);
865 writer.Write (assembly);
871 public int GetAssemblyId (Assembly assembly)
873 return GetAssemblyNameId (assembly.FullName);
876 public int GetAssemblyNameId (string assembly)
878 return (int)_assemblyCache[assembly];
881 private int RegisterAssembly (string assembly, out bool firstTime)
883 if (_assemblyCache.ContainsKey (assembly))
886 return (int)_assemblyCache[assembly];
890 int id = (int)_idGenerator.GetId (0, out firstTime);
891 _assemblyCache.Add (assembly, id);
896 public static void WritePrimitiveValue (BinaryWriter writer, object value)
898 Type type = value.GetType();
900 switch (Type.GetTypeCode (type))
902 case TypeCode.Boolean:
903 writer.Write ((bool)value);
907 writer.Write ((byte) value);
911 writer.Write ((char) value);
914 case TypeCode.DateTime:
915 writer.Write ( ((DateTime)value).ToBinary ());
918 case TypeCode.Decimal:
919 writer.Write (((decimal) value).ToString (CultureInfo.InvariantCulture));
922 case TypeCode.Double:
923 writer.Write ((double) value);
927 writer.Write ((short) value);
931 writer.Write ((int) value);
935 writer.Write ((long) value);
939 writer.Write ((sbyte) value);
942 case TypeCode.Single:
943 writer.Write ((float) value);
946 case TypeCode.UInt16:
947 writer.Write ((ushort) value);
950 case TypeCode.UInt32:
951 writer.Write ((uint) value);
954 case TypeCode.UInt64:
955 writer.Write ((ulong) value);
958 case TypeCode.String:
959 writer.Write ((string) value);
963 if (type == typeof (TimeSpan))
964 writer.Write (((TimeSpan)value).Ticks);
966 throw new NotSupportedException ("Unsupported primitive type: " + value.GetType().FullName);
971 public static void WriteTypeCode (BinaryWriter writer, Type type)
973 writer.Write ((byte) GetTypeTag (type));
976 public static TypeTag GetTypeTag (Type type)
978 if (type == typeof (string)) {
979 return TypeTag.String;
981 else if (BinaryCommon.IsPrimitive (type)) {
982 return TypeTag.PrimitiveType;
984 else if (type == typeof (object)) {
985 return TypeTag.ObjectType;
987 else if (type.IsArray && type.GetArrayRank() == 1 && type.GetElementType() == typeof (object)) {
988 return TypeTag.ArrayOfObject;
990 else if (type.IsArray && type.GetArrayRank() == 1 && type.GetElementType() == typeof (string)){
991 return TypeTag.ArrayOfString;
993 else if (type.IsArray && type.GetArrayRank() == 1 && BinaryCommon.IsPrimitive(type.GetElementType())) {
994 return TypeTag.ArrayOfPrimitiveType;
996 else if (type.Assembly == CorlibAssembly) {
997 return TypeTag.RuntimeType;
1000 return TypeTag.GenericType;
1003 public void WriteTypeSpec (BinaryWriter writer, Type type)
1005 // WARNING Keep in sync with EmitWriteTypeSpec
1007 switch (GetTypeTag (type))
1009 case TypeTag.PrimitiveType:
1010 writer.Write (BinaryCommon.GetTypeCode (type));
1013 case TypeTag.RuntimeType:
1014 string fullName = type.FullName;
1015 // Map System.MonoType to MS.NET's System.RuntimeType,
1016 // when called in remoting context.
1017 // Note that this code does not need to be in sync with
1018 // EmitWriteTypeSpec because serializing a MethodCall
1019 // won't trigger the CodeGenerator.
1020 if (_context.State == StreamingContextStates.Remoting)
1021 if (type == typeof (System.MonoType))
1022 fullName = "System.RuntimeType";
1023 else if (type == typeof (System.MonoType[]))
1024 fullName = "System.RuntimeType[]";
1025 writer.Write (fullName);
1028 case TypeTag.GenericType:
1029 writer.Write (type.FullName);
1031 string asmName = GetForwardedAttribute.GetAssemblyName(type);
1032 writer.Write ((int) GetAssemblyNameId (asmName));
1034 writer.Write ((int)GetAssemblyId (type.Assembly));
1038 case TypeTag.ArrayOfPrimitiveType:
1039 writer.Write (BinaryCommon.GetTypeCode (type.GetElementType()));
1043 // Type spec not needed