private void EmitSerializationCode(ILProcessor ilProcessor, ParameterDefinition valueParam, ParameterDefinition writerParam, TypeDefinition resolved) { ilProcessor.CallMethod(writerParam, _typeHelper.MsgPackWriter.WriteMapHeader, resolved.Fields.Count); foreach (var field in resolved.Fields) { ilProcessor.CallMethod(writerParam, _typeHelper.MsgPackWriter.WriteString, field.Name); ilProcessor.CallStatic(GetTypeSerializeMethod(field.FieldType), (valueParam, field), writerParam); } }
private void BuildDeserializeMethodBody(ILProcessor ilProcessor, TypeReference type, ParameterDefinition readerParam) { if (_typeHelper.MsgPackReader.IsSimpleType(type)) { var deserializeMethod = _typeHelper.MsgPackReader.GetMethodForType(type); ilProcessor.CallMethod(readerParam, deserializeMethod); ilProcessor.Emit(OpCodes.Ret); } else { var resolved = type.Resolve(); if (type.IsPrimitive) { throw new NotImplementedException($"Unsupported primitive {type.FullName}"); } if (type.IsArray) { throw new NotImplementedException("Arrays are not supported"); } if (type.HasGenericParameters) { throw new NotImplementedException("Generic types are not supported"); } else { if (!resolved.HasFields) { throw new NotImplementedException("Empty type is not supported"); } BuildDeserializeComplexClassBody(ilProcessor, readerParam, resolved); } } }
private void BuildSerializeMethodBody(ILProcessor ilProcessor, ParameterDefinition valueParam, ParameterDefinition writerParam) { if (_typeHelper.MsgPackWriter.IsSimpleType(valueParam.ParameterType)) { var serializeMethod = _typeHelper.MsgPackWriter.GetMethodForType(valueParam.ParameterType); ilProcessor.CallMethod(writerParam, serializeMethod, valueParam); ilProcessor.Emit(OpCodes.Ret); } else { var resolved = valueParam.ParameterType.Resolve(); if (valueParam.ParameterType.IsPrimitive) { throw new NotImplementedException($"Unsupported primitive {valueParam.ParameterType.FullName}"); } if (valueParam.ParameterType.IsArray) { throw new NotImplementedException("Arrays are not supported"); } if (valueParam.ParameterType.HasGenericParameters) { throw new NotImplementedException("Generic types are not supported"); } else { if (!resolved.HasFields) { throw new NotImplementedException("Empty type is not supported"); } BuildSerializeComplexClassBody(ilProcessor, valueParam, writerParam, resolved); } } }
private void EmitFieldsAssignmentLoop(ILProcessor ilProcessor, VariableDefinition resultVar, VariableDefinition fieldCountVar, ParameterDefinition readerParam, TypeDefinition resolved) { var iterationVar = ilProcessor.AddVariable(_mainModule.TypeSystem.Int32); var fieldNameVar = ilProcessor.AddVariable(_mainModule.TypeSystem.String); var tempstr1 = ilProcessor.AddVariable(_mainModule.TypeSystem.String); var switchFieldVar = ilProcessor.AddVariable(_mainModule.TypeSystem.String); ilProcessor.For(0, fieldCountVar, 1).Then(() => { ilProcessor.CallMethod(readerParam, _typeHelper.MsgPackReader.ReadString).Store(fieldNameVar); var switchStatement = ilProcessor.Switch(fieldNameVar); foreach (var field in resolved.Fields) { switchStatement.Case(field.Name, () => { if (resolved.IsValueType) { ilProcessor.Emit(OpCodes.Ldloca, resultVar); } else { ilProcessor.Emit(OpCodes.Ldloc, resultVar); } var deserializationMethod = GetTypeDeserializationMethod(field.FieldType); ilProcessor.Emit(OpCodes.Ldarg, readerParam); ilProcessor.Emit(OpCodes.Call, deserializationMethod); ilProcessor.Emit(OpCodes.Stfld, field); }); } }); }
private void BuildDeserializeComplexClassBody(ILProcessor ilProcessor, ParameterDefinition readerParam, TypeDefinition resolved) { var resultVar = ilProcessor.AddVariable(resolved); var fieldCountVar = ilProcessor.AddVariable(_mainModule.TypeSystem.Int32); Instruction retInstr = Instruction.Create(OpCodes.Ret); if (resolved.IsValueType) { ilProcessor.Emit(OpCodes.Ldloca_S, resultVar); ilProcessor.Emit(OpCodes.Initobj, resolved); var mapTempVar = ilProcessor.AddVariable(_mainModule.TypeSystem.Boolean); ilProcessor.Emit(OpCodes.Ldarg, readerParam); ilProcessor.Emit(OpCodes.Ldloca_S, fieldCountVar); ilProcessor.Emit(OpCodes.Call, _typeHelper.MsgPackReader.ReadMapHeader); ilProcessor.Emit(OpCodes.Stloc, mapTempVar); EmitFieldsAssignmentLoop(ilProcessor, resultVar, fieldCountVar, readerParam, resolved); } else { var ifTempVar = ilProcessor.AddVariable(_mainModule.TypeSystem.Boolean); ilProcessor.CallMethod(readerParam, _typeHelper.MsgPackReader.TryReadNil).Store(ifTempVar); ilProcessor.If(ifTempVar).True().Then(() => { ilProcessor.Emit(OpCodes.Ldnull); ilProcessor.Emit(OpCodes.Stloc, resultVar); }).Else(() => { var ctor = resolved.GetConstructors().FirstOrDefault(ctr => ctr.Parameters.Count == 0); if (ctor == null) { throw new InvalidOperationException($"Type {resolved} does not have default constructor"); } ilProcessor.Emit(OpCodes.Newobj, ctor); ilProcessor.Emit(OpCodes.Stloc, resultVar); var mapTempVar = ilProcessor.AddVariable(_mainModule.TypeSystem.Boolean); ilProcessor.Emit(OpCodes.Ldarg, readerParam); ilProcessor.Emit(OpCodes.Ldloca_S, fieldCountVar); ilProcessor.Emit(OpCodes.Call, _typeHelper.MsgPackReader.ReadMapHeader); ilProcessor.Emit(OpCodes.Stloc, mapTempVar); //ilProcessor.CallMethod(readerParam, _typeHelper.MsgPackReader.ReadMapHeader, fieldCountVar).Store(mapTempVar); EmitFieldsAssignmentLoop(ilProcessor, resultVar, fieldCountVar, readerParam, resolved); }); } ilProcessor.Emit(OpCodes.Ldloc, resultVar); ilProcessor.Emit(OpCodes.Ret); }
private void BuildSerializeComplexClassBody(ILProcessor ilProcessor, ParameterDefinition valueParam, ParameterDefinition writerParam, TypeDefinition resolved) { if (!resolved.IsValueType) { ilProcessor.If(valueParam).Null().Then(() => { ilProcessor.CallMethod(writerParam, _typeHelper.MsgPackWriter.WriteNil); }).Else(() => { EmitSerializationCode(ilProcessor, valueParam, writerParam, resolved); }); } else { EmitSerializationCode(ilProcessor, valueParam, writerParam, resolved); } ilProcessor.Emit(OpCodes.Ret); }