private void WriteArray(BinaryWriter writer, long id, Array array) { // There are 4 ways of serializing arrays: // The element GenericArray (7) can be used for all arrays. // The element ArrayOfPrimitiveType (15) can be used for single-dimensional // arrays of primitive types // The element ArrayOfObject (16) can be used for single-dimensional Object arrays // The element ArrayOfString (17) can be used for single-dimensional string arrays Type elementType = array.GetType().GetElementType(); if (elementType == typeof(object) && array.Rank == 1) { WriteObjectArray(writer, id, array); } else if (elementType == typeof(string) && array.Rank == 1) { WriteStringArray(writer, id, array); } else if (BinaryCommon.IsPrimitive(elementType) && array.Rank == 1) { WritePrimitiveTypeArray(writer, id, array); } else { WriteGenericArray(writer, id, array); } }
public static TypeTag GetTypeTag(Type type) { if (type == typeof(string)) { return(TypeTag.String); } else if (BinaryCommon.IsPrimitive(type)) { return(TypeTag.PrimitiveType); } else if (type == typeof(object)) { return(TypeTag.ObjectType); } else if (type.IsArray && type.GetArrayRank() == 1 && type.GetElementType() == typeof(object)) { return(TypeTag.ArrayOfObject); } else if (type.IsArray && type.GetArrayRank() == 1 && type.GetElementType() == typeof(string)) { return(TypeTag.ArrayOfString); } else if (type.IsArray && type.GetArrayRank() == 1 && BinaryCommon.IsPrimitive(type.GetElementType())) { return(TypeTag.ArrayOfPrimitiveType); } else if (type.Assembly == CorlibAssembly) { return(TypeTag.RuntimeType); } else { return(TypeTag.GenericType); } }
public void WriteValue(BinaryWriter writer, Type valueType, object val) { if (val == null) { BinaryCommon.CheckSerializable(valueType, _surrogateSelector, _context); writer.Write((byte)BinaryElement.NullValue); } else if (BinaryCommon.IsPrimitive(val.GetType())) { if (!BinaryCommon.IsPrimitive(valueType)) { // It is a boxed primitive type value writer.Write((byte)BinaryElement.BoxedPrimitiveTypeValue); WriteTypeSpec(writer, val.GetType()); } WritePrimitiveValue(writer, val); } else if (valueType.IsValueType) { // Value types are written embedded in the containing object WriteObjectInstance(writer, val, true); } else if (val is string) { // Strings are written embedded, unless already registered bool firstTime; long id = _idGenerator.GetId(val, out firstTime); if (firstTime) { WriteObjectInstance(writer, val, false); } else { WriteObjectReference(writer, id); } } else { // It is a reference type. Write a forward reference and queue the // object to the pending object list (unless already written). bool firstTime; long id = _idGenerator.GetId(val, out firstTime); if (firstTime) { _pendingObjects.Enqueue(val); } WriteObjectReference(writer, id); } }
private void ReadValue(BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, MemberInfo memberInfo, int[] indices) { object obj; if (BinaryCommon.IsPrimitive(valueType)) { obj = ObjectReader.ReadPrimitiveTypeValue(reader, valueType); this.SetObjectValue(parentObject, fieldName, memberInfo, info, obj, valueType, indices); return; } BinaryElement binaryElement = (BinaryElement)reader.ReadByte(); if (binaryElement == BinaryElement.ObjectReference) { long childObjectId = (long)((ulong)reader.ReadUInt32()); this.RecordFixup(parentObjectId, childObjectId, parentObject, info, fieldName, memberInfo, indices); return; } long num; SerializationInfo info2; this.ReadObject(binaryElement, reader, out num, out obj, out info2); bool flag = false; if (num != 0L) { if (obj.GetType().IsValueType) { this.RecordFixup(parentObjectId, num, parentObject, info, fieldName, memberInfo, indices); flag = true; } if (info == null && !(parentObject is Array)) { this.RegisterObject(num, obj, info2, parentObjectId, memberInfo, null); } else { this.RegisterObject(num, obj, info2, parentObjectId, null, indices); } } if (!flag) { this.SetObjectValue(parentObject, fieldName, memberInfo, info, obj, valueType, indices); } }
public void WriteValue(BinaryWriter writer, Type valueType, object val) { if (val == null) { BinaryCommon.CheckSerializable(valueType, this._surrogateSelector, this._context); writer.Write(10); } else if (BinaryCommon.IsPrimitive(val.GetType())) { if (!BinaryCommon.IsPrimitive(valueType)) { writer.Write(8); this.WriteTypeSpec(writer, val.GetType()); } ObjectWriter.WritePrimitiveValue(writer, val); } else if (valueType.IsValueType) { this.WriteObjectInstance(writer, val, true); } else if (val is string) { bool flag; long id = this._idGenerator.GetId(val, out flag); if (flag) { this.WriteObjectInstance(writer, val, false); } else { this.WriteObjectReference(writer, id); } } else { bool flag2; long id2 = this._idGenerator.GetId(val, out flag2); if (flag2) { this._pendingObjects.Enqueue(val); } this.WriteObjectReference(writer, id2); } }
private void ReadObjectContent(BinaryReader reader, TypeMetadata metadata, long objectId, out object objectInstance, out SerializationInfo info) { if (_filterLevel == TypeFilterLevel.Low) { objectInstance = FormatterServices.GetSafeUninitializedObject(metadata.Type); } else { objectInstance = FormatterServices.GetUninitializedObject(metadata.Type); } _manager.RaiseOnDeserializingEvent(objectInstance); info = metadata.NeedsSerializationInfo ? new SerializationInfo(metadata.Type, new FormatterConverter()) : null; if (metadata.MemberNames != null) { for (int n = 0; n < metadata.FieldCount; n++) { ReadValue(reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberNames[n], null, null); } } else { for (int n = 0; n < metadata.FieldCount; n++) { if (metadata.MemberInfos [n] != null) { ReadValue(reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberInfos[n].Name, metadata.MemberInfos[n], null); } else if (BinaryCommon.IsPrimitive(metadata.MemberTypes[n])) { // Since the member info is null, the type in this // domain does not have this type. Even though we // are not going to store the value, we will read // it from the stream so that we can advance to the // next block. ReadPrimitiveTypeValue(reader, metadata.MemberTypes[n]); } } } }
private void WriteArray(BinaryWriter writer, long id, Array array) { Type elementType = array.GetType().GetElementType(); if (elementType == typeof(object) && array.Rank == 1) { this.WriteObjectArray(writer, id, array); } else if (elementType == typeof(string) && array.Rank == 1) { this.WriteStringArray(writer, id, array); } else if (BinaryCommon.IsPrimitive(elementType) && array.Rank == 1) { this.WritePrimitiveTypeArray(writer, id, array); } else { this.WriteGenericArray(writer, id, array); } }
private void ReadValue(BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, MemberInfo memberInfo, int[] indices) { // Reads a value from the stream and assigns it to the member of an object object val; if (BinaryCommon.IsPrimitive(valueType) && !IsGeneric(memberInfo)) { val = ReadPrimitiveTypeValue(reader, valueType); SetObjectValue(parentObject, fieldName, memberInfo, info, val, valueType, indices); return; } // Gets the object BinaryElement element = (BinaryElement)reader.ReadByte(); if (element == BinaryElement.ObjectReference) { // Just read the id of the referred object and record a fixup long childObjectId = (long)reader.ReadUInt32(); RecordFixup(parentObjectId, childObjectId, parentObject, info, fieldName, memberInfo, indices); return; } long objectId; SerializationInfo objectInfo; ReadObject(element, reader, out objectId, out val, out objectInfo); // There are two cases where the object cannot be assigned to the parent // and a fixup must be used: // 1) When what has been read is not an object, but an id of an object that // has not been read yet (an object reference). This is managed in the // previous block of code. // 2) When the read object is a value type object. Value type fields hold // copies of objects, not references. Thus, if the value object that // has been read has pending fixups, those fixups would be made to the // boxed copy in the ObjectManager, and not in the required object instance // First of all register the fixup, and then the object. ObjectManager is more // efficient if done in this order bool hasFixup = false; if (objectId != 0) { if (val.GetType().IsValueType) { RecordFixup(parentObjectId, objectId, parentObject, info, fieldName, memberInfo, indices); hasFixup = true; } // Register the value if (info == null && !(parentObject is Array)) { RegisterObject(objectId, val, objectInfo, parentObjectId, memberInfo, null); } else { RegisterObject(objectId, val, objectInfo, parentObjectId, null, indices); } } // Assign the value to the parent object, unless there is a fixup if (!hasFixup) { SetObjectValue(parentObject, fieldName, memberInfo, info, val, valueType, indices); } }
static public Type GenerateMetadataType(Type type, StreamingContext context) { string name = type.Name + "__TypeMetadata"; string sufix = ""; int n = 0; while (_module.GetType(name + sufix) != null) { sufix = (++n).ToString(); } name += sufix; MemberInfo[] members = FormatterServices.GetSerializableMembers(type, context); TypeBuilder typeBuilder = _module.DefineType(name, TypeAttributes.Public, typeof(ClrTypeMetadata)); Type[] parameters; MethodBuilder method; ILGenerator gen; // ********************* // METHOD public constructor (Type t): base (t); parameters = new Type[0]; ConstructorBuilder ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, parameters); ConstructorInfo baseCtor = typeof(ClrTypeMetadata).GetConstructor(new Type[] { typeof(Type) }); gen = ctor.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldtoken, type); gen.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); gen.Emit(OpCodes.Call, baseCtor); gen.Emit(OpCodes.Ret); // ********************* // METHOD public override void WriteAssemblies (ObjectWriter ow, BinaryWriter writer); parameters = new Type[] { typeof(ObjectWriter), typeof(BinaryWriter) }; method = typeBuilder.DefineMethod("WriteAssemblies", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), parameters); gen = method.GetILGenerator(); foreach (FieldInfo field in members) { Type memberType = field.FieldType; while (memberType.IsArray) { memberType = memberType.GetElementType(); } if (memberType.Assembly != ObjectWriter.CorlibAssembly) { // EMIT ow.WriteAssembly (writer, memberType.Assembly); gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Ldarg_2); EmitLoadTypeAssembly(gen, memberType, field.Name); gen.EmitCall(OpCodes.Callvirt, typeof(ObjectWriter).GetMethod("WriteAssembly"), null); gen.Emit(OpCodes.Pop); } } gen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(method, typeof(TypeMetadata).GetMethod("WriteAssemblies")); // ********************* // METHOD public override void WriteTypeData (ObjectWriter ow, BinaryWriter writer, bool writeTypes); parameters = new Type[] { typeof(ObjectWriter), typeof(BinaryWriter), typeof(bool) }; method = typeBuilder.DefineMethod("WriteTypeData", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), parameters); gen = method.GetILGenerator(); // EMIT writer.Write (members.Length); gen.Emit(OpCodes.Ldarg_2); gen.Emit(OpCodes.Ldc_I4, members.Length); EmitWrite(gen, typeof(int)); // Names of fields foreach (FieldInfo field in members) { // EMIT writer.Write (name); gen.Emit(OpCodes.Ldarg_2); gen.Emit(OpCodes.Ldstr, field.Name); EmitWrite(gen, typeof(string)); } Label falseLabel = gen.DefineLabel(); gen.Emit(OpCodes.Ldarg_3); gen.Emit(OpCodes.Brfalse, falseLabel); // Types of fields foreach (FieldInfo field in members) { // EMIT writer.Write ((byte) ObjectWriter.GetTypeTag (type)); gen.Emit(OpCodes.Ldarg_2); gen.Emit(OpCodes.Ldc_I4_S, (byte)ObjectWriter.GetTypeTag(field.FieldType)); EmitWrite(gen, typeof(byte)); } // Type specs of fields foreach (FieldInfo field in members) { // EMIT ow.WriteTypeSpec (writer, field.FieldType); EmitWriteTypeSpec(gen, field.FieldType, field.Name); } gen.MarkLabel(falseLabel); gen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(method, typeof(TypeMetadata).GetMethod("WriteTypeData")); // ********************* // METHOD public override void WriteObjectData (ObjectWriter ow, BinaryWriter writer, object data) parameters = new Type[] { typeof(ObjectWriter), typeof(BinaryWriter), typeof(object) }; method = typeBuilder.DefineMethod("WriteObjectData", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), parameters); gen = method.GetILGenerator(); LocalBuilder localBuilder = gen.DeclareLocal(type); OpCode lload = OpCodes.Ldloc; gen.Emit(OpCodes.Ldarg_3); if (type.IsValueType) { gen.Emit(OpCodes.Unbox, type); LoadFromPtr(gen, type); lload = OpCodes.Ldloca_S; } else { gen.Emit(OpCodes.Castclass, type); } gen.Emit(OpCodes.Stloc, localBuilder); foreach (FieldInfo field in members) { // EMIT ow.WriteValue (writer, ((FieldInfo)members[n]).FieldType, values[n]); Type ftype = field.FieldType; if (BinaryCommon.IsPrimitive(ftype)) { gen.Emit(OpCodes.Ldarg_2); gen.Emit(lload, localBuilder); if (ftype == typeof(DateTime) || ftype == typeof(TimeSpan) || ftype == typeof(decimal)) { gen.Emit(OpCodes.Ldflda, field); } else { gen.Emit(OpCodes.Ldfld, field); } EmitWritePrimitiveValue(gen, ftype); } else { gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Ldarg_2); gen.Emit(OpCodes.Ldtoken, ftype); gen.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); gen.Emit(lload, localBuilder); gen.Emit(OpCodes.Ldfld, field); if (ftype.IsValueType) { gen.Emit(OpCodes.Box, ftype); } gen.EmitCall(OpCodes.Call, typeof(ObjectWriter).GetMethod("WriteValue"), null); } } gen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(method, typeof(TypeMetadata).GetMethod("WriteObjectData")); return(typeBuilder.CreateType()); }
public static Type GenerateMetadataTypeInternal(Type type, StreamingContext context) { string text = type.Name + "__TypeMetadata"; string str = string.Empty; int num = 0; while (CodeGenerator._module.GetType(text + str) != null) { int num2; num = (num2 = num + 1); str = num2.ToString(); } text += str; MemberInfo[] serializableMembers = FormatterServices.GetSerializableMembers(type, context); TypeBuilder typeBuilder = CodeGenerator._module.DefineType(text, TypeAttributes.Public, typeof(ClrTypeMetadata)); Type[] parameterTypes = Type.EmptyTypes; ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, parameterTypes); ConstructorInfo constructor = typeof(ClrTypeMetadata).GetConstructor(new Type[] { typeof(Type) }); ILGenerator ilgenerator = constructorBuilder.GetILGenerator(); ilgenerator.Emit(OpCodes.Ldarg_0); ilgenerator.Emit(OpCodes.Ldtoken, type); ilgenerator.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); ilgenerator.Emit(OpCodes.Call, constructor); ilgenerator.Emit(OpCodes.Ret); parameterTypes = new Type[] { typeof(ObjectWriter), typeof(BinaryWriter) }; MethodBuilder methodBuilder = typeBuilder.DefineMethod("WriteAssemblies", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual, typeof(void), parameterTypes); ilgenerator = methodBuilder.GetILGenerator(); foreach (FieldInfo fieldInfo in serializableMembers) { Type type2 = fieldInfo.FieldType; while (type2.IsArray) { type2 = type2.GetElementType(); } if (type2.Assembly != ObjectWriter.CorlibAssembly) { ilgenerator.Emit(OpCodes.Ldarg_1); ilgenerator.Emit(OpCodes.Ldarg_2); CodeGenerator.EmitLoadTypeAssembly(ilgenerator, type2, fieldInfo.Name); ilgenerator.EmitCall(OpCodes.Callvirt, typeof(ObjectWriter).GetMethod("WriteAssembly"), null); ilgenerator.Emit(OpCodes.Pop); } } ilgenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, typeof(TypeMetadata).GetMethod("WriteAssemblies")); parameterTypes = new Type[] { typeof(ObjectWriter), typeof(BinaryWriter), typeof(bool) }; methodBuilder = typeBuilder.DefineMethod("WriteTypeData", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual, typeof(void), parameterTypes); ilgenerator = methodBuilder.GetILGenerator(); ilgenerator.Emit(OpCodes.Ldarg_2); ilgenerator.Emit(OpCodes.Ldc_I4, serializableMembers.Length); CodeGenerator.EmitWrite(ilgenerator, typeof(int)); foreach (FieldInfo fieldInfo2 in serializableMembers) { ilgenerator.Emit(OpCodes.Ldarg_2); ilgenerator.Emit(OpCodes.Ldstr, fieldInfo2.Name); CodeGenerator.EmitWrite(ilgenerator, typeof(string)); } Label label = ilgenerator.DefineLabel(); ilgenerator.Emit(OpCodes.Ldarg_3); ilgenerator.Emit(OpCodes.Brfalse, label); foreach (FieldInfo fieldInfo3 in serializableMembers) { ilgenerator.Emit(OpCodes.Ldarg_2); ilgenerator.Emit(OpCodes.Ldc_I4_S, (byte)ObjectWriter.GetTypeTag(fieldInfo3.FieldType)); CodeGenerator.EmitWrite(ilgenerator, typeof(byte)); } foreach (FieldInfo fieldInfo4 in serializableMembers) { CodeGenerator.EmitWriteTypeSpec(ilgenerator, fieldInfo4.FieldType, fieldInfo4.Name); } ilgenerator.MarkLabel(label); ilgenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, typeof(TypeMetadata).GetMethod("WriteTypeData")); parameterTypes = new Type[] { typeof(ObjectWriter), typeof(BinaryWriter), typeof(object) }; methodBuilder = typeBuilder.DefineMethod("WriteObjectData", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual, typeof(void), parameterTypes); ilgenerator = methodBuilder.GetILGenerator(); LocalBuilder local = ilgenerator.DeclareLocal(type); OpCode opcode = OpCodes.Ldloc; ilgenerator.Emit(OpCodes.Ldarg_3); if (type.IsValueType) { ilgenerator.Emit(OpCodes.Unbox, type); CodeGenerator.LoadFromPtr(ilgenerator, type); opcode = OpCodes.Ldloca_S; } else { ilgenerator.Emit(OpCodes.Castclass, type); } ilgenerator.Emit(OpCodes.Stloc, local); foreach (FieldInfo fieldInfo5 in serializableMembers) { Type fieldType = fieldInfo5.FieldType; if (BinaryCommon.IsPrimitive(fieldType)) { ilgenerator.Emit(OpCodes.Ldarg_2); ilgenerator.Emit(opcode, local); if (fieldType == typeof(DateTime) || fieldType == typeof(TimeSpan) || fieldType == typeof(decimal)) { ilgenerator.Emit(OpCodes.Ldflda, fieldInfo5); } else { ilgenerator.Emit(OpCodes.Ldfld, fieldInfo5); } CodeGenerator.EmitWritePrimitiveValue(ilgenerator, fieldType); } else { ilgenerator.Emit(OpCodes.Ldarg_1); ilgenerator.Emit(OpCodes.Ldarg_2); ilgenerator.Emit(OpCodes.Ldtoken, fieldType); ilgenerator.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); ilgenerator.Emit(opcode, local); ilgenerator.Emit(OpCodes.Ldfld, fieldInfo5); if (fieldType.IsValueType) { ilgenerator.Emit(OpCodes.Box, fieldType); } ilgenerator.EmitCall(OpCodes.Call, typeof(ObjectWriter).GetMethod("WriteValue"), null); } } ilgenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, typeof(TypeMetadata).GetMethod("WriteObjectData")); return(typeBuilder.CreateType()); }