private void WriteMemberSetup(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, string memberName, Type memberType, object?memberData, WriteObjectInfo?memberObjectInfo) { NameInfo newMemberNameInfo = MemberToNameInfo(memberName); // newMemberNameInfo contains the member type if (memberObjectInfo != null) { newMemberNameInfo._assemId = memberObjectInfo._assemId; } newMemberNameInfo._type = memberType; // newTypeNameInfo contains the data type NameInfo newTypeNameInfo; if (memberObjectInfo == null) { newTypeNameInfo = TypeToNameInfo(memberType); } else { newTypeNameInfo = TypeToNameInfo(memberObjectInfo); } newMemberNameInfo._transmitTypeOnObject = memberNameInfo._transmitTypeOnObject; newMemberNameInfo._isParentTypeOnObject = memberNameInfo._isParentTypeOnObject; WriteMembers(newMemberNameInfo, newTypeNameInfo, memberData, objectInfo, typeNameInfo, memberObjectInfo); PutNameInfo(newMemberNameInfo); PutNameInfo(newTypeNameInfo); }
internal void Serialize(object graph, BinaryFormatterWriter serWriter) { if (graph == null) { throw new ArgumentNullException(nameof(graph)); } if (serWriter == null) { throw new ArgumentNullException(nameof(serWriter)); } _serWriter = serWriter; serWriter.WriteBegin(); long headerId = 0; object?obj; bool isNew; // allocations if methodCall or methodResponse and no graph _idGenerator = new ObjectIDGenerator(); _objectQueue = new Queue <object>(); _formatterConverter = new FormatterConverter(); _serObjectInfoInit = new SerObjectInfoInit(); _topId = InternalGetId(graph, false, null, out isNew); headerId = -1; WriteSerializedStreamHeader(_topId, headerId); _objectQueue.Enqueue(graph); while ((obj = GetNext(out long objectId)) != null) { WriteObjectInfo?objectInfo = null; // GetNext will return either an object or a WriteObjectInfo. // A WriteObjectInfo is returned if this object was member of another object if (obj is WriteObjectInfo) { objectInfo = (WriteObjectInfo)obj; } else { objectInfo = WriteObjectInfo.Serialize(obj, _surrogates, _context, _serObjectInfoInit, _formatterConverter, this, _binder); objectInfo._assemId = GetAssemblyId(objectInfo); } objectInfo._objectId = objectId; NameInfo typeNameInfo = TypeToNameInfo(objectInfo); Write(objectInfo, typeNameInfo, typeNameInfo); PutNameInfo(typeNameInfo); objectInfo.ObjectEnd(); } serWriter.WriteSerializationHeaderEnd(); serWriter.WriteEnd(); // Invoke OnSerialized Event _objectManager.RaiseOnSerializedEvent(); }
// From the type create the BinaryTypeEnum and typeInformation which describes the type on the wire internal static BinaryTypeEnum GetBinaryTypeInfo(Type type, WriteObjectInfo?objectInfo, string?typeName, ObjectWriter objectWriter, out object?typeInformation, out int assemId) { BinaryTypeEnum binaryTypeEnum; assemId = 0; typeInformation = null; if (ReferenceEquals(type, Converter.s_typeofString)) { binaryTypeEnum = BinaryTypeEnum.String; } else if (((objectInfo == null) || ((objectInfo != null) && !objectInfo._isSi)) && (ReferenceEquals(type, Converter.s_typeofObject))) { // If objectInfo.Si then can be a surrogate which will change the type binaryTypeEnum = BinaryTypeEnum.Object; } else if (ReferenceEquals(type, Converter.s_typeofStringArray)) { binaryTypeEnum = BinaryTypeEnum.StringArray; } else if (ReferenceEquals(type, Converter.s_typeofObjectArray)) { binaryTypeEnum = BinaryTypeEnum.ObjectArray; } else if (Converter.IsPrimitiveArray(type, out typeInformation)) { binaryTypeEnum = BinaryTypeEnum.PrimitiveArray; } else { InternalPrimitiveTypeE primitiveTypeEnum = objectWriter.ToCode(type); switch (primitiveTypeEnum) { case InternalPrimitiveTypeE.Invalid: string?assembly = null; if (objectInfo == null) { assembly = type.Assembly.FullName; typeInformation = type.FullName; } else { assembly = objectInfo.GetAssemblyString(); typeInformation = objectInfo.GetTypeFullName(); } Debug.Assert(assembly != null); if (assembly.Equals(Converter.s_urtAssemblyString) || assembly.Equals(Converter.s_urtAlternativeAssemblyString)) { binaryTypeEnum = BinaryTypeEnum.ObjectUrt; assemId = 0; } else { binaryTypeEnum = BinaryTypeEnum.ObjectUser; Debug.Assert(objectInfo != null, "[BinaryConverter.GetBinaryTypeInfo]objectInfo null for user object"); assemId = (int)objectInfo._assemId; if (assemId == 0) { throw new SerializationException(SR.Format(SR.Serialization_AssemblyId, typeInformation)); } } break; default: binaryTypeEnum = BinaryTypeEnum.Primitive; typeInformation = primitiveTypeEnum; break; } } return(binaryTypeEnum); }
// Writes out an array private void WriteArray(WriteObjectInfo objectInfo, NameInfo?memberNameInfo, WriteObjectInfo?memberObjectInfo) { bool isAllocatedMemberNameInfo = false; if (memberNameInfo == null) { memberNameInfo = TypeToNameInfo(objectInfo); isAllocatedMemberNameInfo = true; } memberNameInfo._isArray = true; long objectId = objectInfo._objectId; memberNameInfo._objectId = objectInfo._objectId; // Get array type Array array = (Array)objectInfo._obj !; //Type arrayType = array.GetType(); Type arrayType = objectInfo._objectType !; // Get type of array element Type arrayElemType = arrayType.GetElementType() !; WriteObjectInfo?arrayElemObjectInfo = null; if (!arrayElemType.IsPrimitive) { Debug.Assert(_serObjectInfoInit != null && _formatterConverter != null); arrayElemObjectInfo = WriteObjectInfo.Serialize(arrayElemType, _surrogates, _context, _serObjectInfoInit, _formatterConverter, _binder); arrayElemObjectInfo._assemId = GetAssemblyId(arrayElemObjectInfo); } NameInfo arrayElemTypeNameInfo = arrayElemObjectInfo == null? TypeToNameInfo(arrayElemType) : TypeToNameInfo(arrayElemObjectInfo); arrayElemTypeNameInfo._isArray = arrayElemTypeNameInfo._type !.IsArray; NameInfo arrayNameInfo = memberNameInfo; arrayNameInfo._objectId = objectId; arrayNameInfo._isArray = true; arrayElemTypeNameInfo._objectId = objectId; arrayElemTypeNameInfo._transmitTypeOnMember = memberNameInfo._transmitTypeOnMember; arrayElemTypeNameInfo._transmitTypeOnObject = memberNameInfo._transmitTypeOnObject; arrayElemTypeNameInfo._isParentTypeOnObject = memberNameInfo._isParentTypeOnObject; // Get rank and length information int rank = array.Rank; int[] lengthA = new int[rank]; int[] lowerBoundA = new int[rank]; int[] upperBoundA = new int[rank]; for (int i = 0; i < rank; i++) { lengthA[i] = array.GetLength(i); lowerBoundA[i] = array.GetLowerBound(i); upperBoundA[i] = array.GetUpperBound(i); } InternalArrayTypeE arrayEnum; if (arrayElemTypeNameInfo._isArray) { arrayEnum = rank == 1 ? InternalArrayTypeE.Jagged : InternalArrayTypeE.Rectangular; } else if (rank == 1) { arrayEnum = InternalArrayTypeE.Single; } else { arrayEnum = InternalArrayTypeE.Rectangular; } arrayElemTypeNameInfo._arrayEnum = arrayEnum; Debug.Assert(_serWriter != null); // Byte array if ((ReferenceEquals(arrayElemType, Converter.s_typeofByte)) && (rank == 1) && (lowerBoundA[0] == 0)) { _serWriter.WriteObjectByteArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0], (byte[])array); return; } if (ReferenceEquals(arrayElemType, Converter.s_typeofObject) || Nullable.GetUnderlyingType(arrayElemType) != null) { memberNameInfo._transmitTypeOnMember = true; arrayElemTypeNameInfo._transmitTypeOnMember = true; } if (CheckTypeFormat(_formatterEnums._typeFormat, FormatterTypeStyle.TypesAlways)) { memberNameInfo._transmitTypeOnObject = true; arrayElemTypeNameInfo._transmitTypeOnObject = true; } if (arrayEnum == InternalArrayTypeE.Single) { // Single Dimensional array // BinaryFormatter array of primitive types is written out in the WriteSingleArray statement // as a byte buffer _serWriter.WriteSingleArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0], array); if (!(Converter.IsWriteAsByteArray(arrayElemTypeNameInfo._primitiveTypeEnum) && (lowerBoundA[0] == 0))) { object[]? objectA = null; if (!arrayElemType.IsValueType) { // Non-primitive type array objectA = (object[])array; } int upperBound = upperBoundA[0] + 1; for (int i = lowerBoundA[0]; i < upperBound; i++) { if (objectA == null) { WriteArrayMember(objectInfo, arrayElemTypeNameInfo, array.GetValue(i)); } else { WriteArrayMember(objectInfo, arrayElemTypeNameInfo, objectA[i]); } } _serWriter.WriteItemEnd(); } } else if (arrayEnum == InternalArrayTypeE.Jagged) { // Jagged Array arrayNameInfo._objectId = objectId; _serWriter.WriteJaggedArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0]); var objectA = (Array)array; for (int i = lowerBoundA[0]; i < upperBoundA[0] + 1; i++) { WriteArrayMember(objectInfo, arrayElemTypeNameInfo, objectA.GetValue(i)); } _serWriter.WriteItemEnd(); } else { // Rectangle Array // Get the length for all the ranks arrayNameInfo._objectId = objectId; _serWriter.WriteRectangleArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, rank, lengthA, lowerBoundA); // Check for a length of zero bool bzero = false; for (int i = 0; i < rank; i++) { if (lengthA[i] == 0) { bzero = true; break; } } if (!bzero) { WriteRectangle(objectInfo, rank, lengthA, array, arrayElemTypeNameInfo, lowerBoundA); } _serWriter.WriteItemEnd(); } _serWriter.WriteObjectEnd(memberNameInfo, arrayNameInfo); PutNameInfo(arrayElemTypeNameInfo); if (isAllocatedMemberNameInfo) { PutNameInfo(memberNameInfo); } }
// Writes the members of an object private void WriteMembers(NameInfo memberNameInfo, NameInfo memberTypeNameInfo, object?memberData, WriteObjectInfo objectInfo, NameInfo typeNameInfo, WriteObjectInfo?memberObjectInfo) { Type?memberType = memberNameInfo._type; bool assignUniqueIdToValueType = false; // Types are transmitted for a member as follows: // The member is of type object // The member object of type is ISerializable and // Binary - Types always transmitted. if (ReferenceEquals(memberType, Converter.s_typeofObject) || Nullable.GetUnderlyingType(memberType !) != null) { memberTypeNameInfo._transmitTypeOnMember = true; memberNameInfo._transmitTypeOnMember = true; } if (CheckTypeFormat(_formatterEnums._typeFormat, FormatterTypeStyle.TypesAlways) || (objectInfo._isSi)) { memberTypeNameInfo._transmitTypeOnObject = true; memberNameInfo._transmitTypeOnObject = true; memberNameInfo._isParentTypeOnObject = true; } if (CheckForNull(objectInfo, memberNameInfo, memberTypeNameInfo, memberData)) { return; } object outObj = memberData !; Type? outType = null; // If member type does not equal data type, transmit type on object. if (memberTypeNameInfo._primitiveTypeEnum == InternalPrimitiveTypeE.Invalid) { outType = GetType(outObj); if (!ReferenceEquals(memberType, outType)) { memberTypeNameInfo._transmitTypeOnMember = true; memberNameInfo._transmitTypeOnMember = true; } } if (ReferenceEquals(memberType, Converter.s_typeofObject)) { assignUniqueIdToValueType = true; memberType = GetType(memberData !); if (memberObjectInfo == null) { TypeToNameInfo(memberType, memberTypeNameInfo); } else { TypeToNameInfo(memberObjectInfo, memberTypeNameInfo); } } if (memberObjectInfo != null && memberObjectInfo._isArray) { // outObj is an array. It can never be a value type. long arrayId = Schedule(outObj, false, null, memberObjectInfo); if (arrayId > 0) { // Array as object memberNameInfo._objectId = arrayId; WriteObjectRef(memberNameInfo, arrayId); } else { Debug.Assert(_serWriter != null); // Nested Array _serWriter.WriteMemberNested(memberNameInfo); memberObjectInfo._objectId = arrayId; memberNameInfo._objectId = arrayId; WriteArray(memberObjectInfo, memberNameInfo, memberObjectInfo); objectInfo.ObjectEnd(); } return; } if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData !)) { if (outType == null) { outType = GetType(outObj); } long memberObjectId = Schedule(outObj, assignUniqueIdToValueType, outType, memberObjectInfo); if (memberObjectId < 0) { Debug.Assert(memberObjectInfo != null); // Nested object memberObjectInfo._objectId = memberObjectId; NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo); newTypeNameInfo._objectId = memberObjectId; Write(memberObjectInfo, memberNameInfo, newTypeNameInfo); PutNameInfo(newTypeNameInfo); memberObjectInfo.ObjectEnd(); } else { // Object reference memberNameInfo._objectId = memberObjectId; WriteObjectRef(memberNameInfo, memberObjectId); } } }
internal void WriteObjectByteArray(NameInfo memberNameInfo, NameInfo arrayNameInfo, WriteObjectInfo?objectInfo, NameInfo arrayElemTypeNameInfo, int length, int lowerBound, byte[] byteA) { InternalWriteItemNull(); WriteSingleArray(memberNameInfo, arrayNameInfo, objectInfo, arrayElemTypeNameInfo, length, lowerBound, byteA); }
internal void WriteRectangleArray(NameInfo memberNameInfo, NameInfo arrayNameInfo, WriteObjectInfo?objectInfo, NameInfo arrayElemTypeNameInfo, int rank, int[] lengthA, int[] lowerBoundA) { InternalWriteItemNull(); BinaryArrayTypeEnum binaryArrayTypeEnum = BinaryArrayTypeEnum.Rectangular; object? typeInformation = null; int assemId = 0; BinaryTypeEnum binaryTypeEnum = BinaryTypeConverter.GetBinaryTypeInfo(arrayElemTypeNameInfo._type !, objectInfo, arrayElemTypeNameInfo.NIname, _objectWriter, out typeInformation, out assemId); if (_binaryArray == null) { _binaryArray = new BinaryArray(); } for (int i = 0; i < rank; i++) { if (lowerBoundA[i] != 0) { binaryArrayTypeEnum = BinaryArrayTypeEnum.RectangularOffset; break; } } _binaryArray.Set((int)arrayNameInfo._objectId, rank, lengthA, lowerBoundA, binaryTypeEnum, typeInformation, binaryArrayTypeEnum, assemId); _binaryArray.Write(this); }
internal void WriteJaggedArray(NameInfo memberNameInfo, NameInfo arrayNameInfo, WriteObjectInfo?objectInfo, NameInfo arrayElemTypeNameInfo, int length, int lowerBound) { InternalWriteItemNull(); BinaryArrayTypeEnum binaryArrayTypeEnum; var lengthA = new int[1]; lengthA[0] = length; int[]? lowerBoundA = null; object?typeInformation = null; int assemId = 0; if (lowerBound == 0) { binaryArrayTypeEnum = BinaryArrayTypeEnum.Jagged; } else { binaryArrayTypeEnum = BinaryArrayTypeEnum.JaggedOffset; lowerBoundA = new int[1]; lowerBoundA[0] = lowerBound; } BinaryTypeEnum binaryTypeEnum = BinaryTypeConverter.GetBinaryTypeInfo(arrayElemTypeNameInfo._type !, objectInfo, arrayElemTypeNameInfo.NIname, _objectWriter, out typeInformation, out assemId); if (_binaryArray == null) { _binaryArray = new BinaryArray(); } _binaryArray.Set((int)arrayNameInfo._objectId, 1, lengthA, lowerBoundA, binaryTypeEnum, typeInformation, binaryArrayTypeEnum, assemId); _binaryArray.Write(this); }
internal void WriteSingleArray(NameInfo memberNameInfo, NameInfo arrayNameInfo, WriteObjectInfo?objectInfo, NameInfo arrayElemTypeNameInfo, int length, int lowerBound, Array array) { InternalWriteItemNull(); BinaryArrayTypeEnum binaryArrayTypeEnum; var lengthA = new int[1]; lengthA[0] = length; int[]? lowerBoundA = null; object?typeInformation = null; if (lowerBound == 0) { binaryArrayTypeEnum = BinaryArrayTypeEnum.Single; } else { binaryArrayTypeEnum = BinaryArrayTypeEnum.SingleOffset; lowerBoundA = new int[1]; lowerBoundA[0] = lowerBound; } int assemId; BinaryTypeEnum binaryTypeEnum = BinaryTypeConverter.GetBinaryTypeInfo( arrayElemTypeNameInfo._type !, objectInfo, arrayElemTypeNameInfo.NIname, _objectWriter, out typeInformation, out assemId); if (_binaryArray == null) { _binaryArray = new BinaryArray(); } _binaryArray.Set((int)arrayNameInfo._objectId, 1, lengthA, lowerBoundA, binaryTypeEnum, typeInformation, binaryArrayTypeEnum, assemId); _binaryArray.Write(this); if (Converter.IsWriteAsByteArray(arrayElemTypeNameInfo._primitiveTypeEnum) && (lowerBound == 0)) { //array is written out as an array of bytes if (arrayElemTypeNameInfo._primitiveTypeEnum == InternalPrimitiveTypeE.Byte) { WriteBytes((byte[])array); } else if (arrayElemTypeNameInfo._primitiveTypeEnum == InternalPrimitiveTypeE.Char) { WriteChars((char[])array); } else { WriteArrayAsBytes(array, Converter.TypeLength(arrayElemTypeNameInfo._primitiveTypeEnum)); } } }