private LocalBuilder ReadValue(Type type, string name, string ns) { LocalBuilder value = _ilg.DeclareLocal(type, "valueRead"); LocalBuilder?nullableValue = null; int nullables = 0; while (type.IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfNullable) { nullables++; type = type.GetGenericArguments()[0]; } PrimitiveDataContract?primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type); if ((primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) || nullables != 0 || type.IsValueType) { LocalBuilder objectId = _ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ReadAttributesMethod, _xmlReaderArg); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ReadIfNullOrRefMethod, _xmlReaderArg, type, DataContract.IsTypeSerializable(type)); _ilg.Stloc(objectId); // Deserialize null _ilg.If(objectId, Cmp.EqualTo, Globals.NullObjectId); if (nullables != 0) { _ilg.LoadAddress(value); _ilg.InitObj(value.LocalType); } else if (type.IsValueType) { ThrowValidationException(SR.Format(SR.ValueTypeCannotBeNull, DataContract.GetClrTypeFullName(type))); } else { _ilg.Load(null); _ilg.Stloc(value); } // Deserialize value // Compare against Globals.NewObjectId, which is set to string.Empty _ilg.ElseIfIsEmptyString(objectId); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod); _ilg.Stloc(objectId); if (type.IsValueType) { _ilg.IfNotIsEmptyString(objectId); ThrowValidationException(SR.Format(SR.ValueTypeCannotHaveId, DataContract.GetClrTypeFullName(type))); _ilg.EndIf(); } if (nullables != 0) { nullableValue = value; value = _ilg.DeclareLocal(type, "innerValueRead"); } if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) { _ilg.Call(_xmlReaderArg, primitiveContract.XmlFormatReaderMethod); _ilg.Stloc(value); if (!type.IsValueType) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, value); } } else { InternalDeserialize(value, type, name, ns); } // Deserialize ref _ilg.Else(); if (type.IsValueType) { ThrowValidationException(SR.Format(SR.ValueTypeCannotHaveRef, DataContract.GetClrTypeFullName(type))); } else { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetExistingObjectMethod, objectId, type, name, ns); _ilg.ConvertValue(Globals.TypeOfObject, type); _ilg.Stloc(value); } _ilg.EndIf(); if (nullableValue != null) { _ilg.If(objectId, Cmp.NotEqualTo, Globals.NullObjectId); WrapNullableObject(value, nullableValue, nullables); _ilg.EndIf(); value = nullableValue; } } else { InternalDeserialize(value, type, name, ns); } return(value); }
private void ReadMembers(ClassDataContract classContract, LocalBuilder extensionDataLocal) { int memberCount = classContract.MemberNames.Length; _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, memberCount); LocalBuilder memberIndexLocal = _ilg.DeclareLocal(Globals.TypeOfInt, "memberIndex", -1); int firstRequiredMember; bool[] requiredMembers = GetRequiredMembers(classContract, out firstRequiredMember); bool hasRequiredMembers = (firstRequiredMember < memberCount); LocalBuilder requiredIndexLocal = hasRequiredMembers ? _ilg.DeclareLocal(Globals.TypeOfInt, "requiredIndex", firstRequiredMember) : null; object forReadElements = _ilg.For(null, null, null); _ilg.Call(null, XmlFormatGeneratorStatics.MoveToNextElementMethod, _xmlReaderArg); _ilg.IfFalseBreak(forReadElements); if (hasRequiredMembers) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetMemberIndexWithRequiredMembersMethod, _xmlReaderArg, _memberNamesArg, _memberNamespacesArg, memberIndexLocal, requiredIndexLocal, extensionDataLocal); } else { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetMemberIndexMethod, _xmlReaderArg, _memberNamesArg, _memberNamespacesArg, memberIndexLocal, extensionDataLocal); } Label[] memberLabels = _ilg.Switch(memberCount); ReadMembers(classContract, requiredMembers, memberLabels, memberIndexLocal, requiredIndexLocal); _ilg.EndSwitch(); _ilg.EndFor(); if (hasRequiredMembers) { _ilg.If(requiredIndexLocal, Cmp.LessThan, memberCount); _ilg.Call(null, XmlFormatGeneratorStatics.ThrowRequiredMemberMissingExceptionMethod, _xmlReaderArg, memberIndexLocal, requiredIndexLocal, _memberNamesArg); _ilg.EndIf(); } }
private void WriteValue(LocalBuilder memberValue, bool writeXsiType) { Type memberType = memberValue.LocalType; bool isNullableOfT = (memberType.IsGenericType && memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable); if (memberType.IsValueType && !isNullableOfT) { PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType); if (primitiveContract != null && !writeXsiType) { _ilg.Call(_xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue); } else { InternalSerialize(XmlFormatGeneratorStatics.InternalSerializeMethod, memberValue, memberType, writeXsiType); } } else { if (isNullableOfT) { memberValue = UnwrapNullableObject(memberValue);//Leaves !HasValue on stack memberType = memberValue.LocalType; } else { _ilg.Load(memberValue); _ilg.Load(null); _ilg.Ceq(); } _ilg.If(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.WriteNullMethod, _xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType)); _ilg.Else(); PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType); if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject && !writeXsiType) { if (isNullableOfT) { _ilg.Call(_xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue); } else { _ilg.Call(_contextArg, primitiveContract.XmlFormatContentWriterMethod, _xmlWriterArg, memberValue); } } else { if (memberType == Globals.TypeOfObject ||//boxed Nullable<T> memberType == Globals.TypeOfValueType || ((IList)Globals.TypeOfNullable.GetInterfaces()).Contains(memberType)) { _ilg.Load(memberValue); _ilg.ConvertValue(memberValue.LocalType, Globals.TypeOfObject); memberValue = _ilg.DeclareLocal(Globals.TypeOfObject, "unwrappedMemberValue"); memberType = memberValue.LocalType; _ilg.Stloc(memberValue); _ilg.If(memberValue, Cmp.EqualTo, null); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.WriteNullMethod, _xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType)); _ilg.Else(); } InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod), memberValue, memberType, writeXsiType); if (memberType == Globals.TypeOfObject) //boxed Nullable<T> { _ilg.EndIf(); } } _ilg.EndIf(); } }