private void ReadSimpleDictionary(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract, Type keyValueType, object dictionary) { Type[] keyValueTypes = keyValueType.GetGenericArguments(); Type keyType = keyValueTypes[0]; Type valueType = keyValueTypes[1]; int keyTypeNullableDepth = 0; while (keyType.IsGenericType && keyType.GetGenericTypeDefinition() == Globals.TypeOfNullable) { keyTypeNullableDepth++; keyType = keyType.GetGenericArguments()[0]; } ClassDataContract keyValueDataContract = (ClassDataContract)collectionContract.ItemContract; DataContract keyDataContract = keyValueDataContract.Members[0].MemberTypeContract; KeyParseMode keyParseMode = KeyParseMode.Fail; if (keyType == Globals.TypeOfString || keyType == Globals.TypeOfObject) { keyParseMode = KeyParseMode.AsString; } else if (keyType.IsEnum) { keyParseMode = KeyParseMode.UsingParseEnum; } else if (keyDataContract.ParseMethod != null) { keyParseMode = KeyParseMode.UsingCustomParse; } if (keyParseMode == KeyParseMode.Fail) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( SR.Format(SR.KeyTypeCannotBeParsedInSimpleDictionary, DataContract.GetClrTypeFullName(collectionContract.UnderlyingType), DataContract.GetClrTypeFullName(keyType)) )); } while (true) { XmlNodeType nodeType = xmlReader.MoveToContent(); if (nodeType == XmlNodeType.EndElement) { return; } if (nodeType != XmlNodeType.Element) { throw XmlObjectSerializerReadContext.CreateUnexpectedStateException(XmlNodeType.Element, xmlReader); } context.IncrementItemCount(1); string keyString = XmlObjectSerializerReadContextComplexJson.GetJsonMemberName(xmlReader); object pairKey; if (keyParseMode == KeyParseMode.UsingParseEnum) { pairKey = Enum.Parse(keyType, keyString); } else if (keyParseMode == KeyParseMode.UsingCustomParse) { TypeCode typeCode = Type.GetTypeCode(keyDataContract.UnderlyingType); pairKey = typeCode switch { TypeCode.Boolean => bool.Parse(keyString), TypeCode.Int16 => short.Parse(keyString), TypeCode.Int32 => int.Parse(keyString), TypeCode.Int64 => long.Parse(keyString), TypeCode.Char => char.Parse(keyString), TypeCode.Byte => byte.Parse(keyString), TypeCode.SByte => sbyte.Parse(keyString), TypeCode.Double => double.Parse(keyString), TypeCode.Decimal => decimal.Parse(keyString), TypeCode.Single => float.Parse(keyString), TypeCode.UInt16 => ushort.Parse(keyString), TypeCode.UInt32 => uint.Parse(keyString), TypeCode.UInt64 => ulong.Parse(keyString), _ => keyDataContract.ParseMethod.Invoke(null, new object[] { keyString }), }; } else { pairKey = keyString; } if (keyTypeNullableDepth > 0) { throw new NotImplementedException("keyTypeNullableDepth > 0"); } object pairValue = ReflectionReadValue(xmlReader, context, valueType, string.Empty, string.Empty); ((IDictionary)dictionary).Add(pairKey, pairValue); } }
private void ReadSimpleDictionary(CollectionDataContract collectionContract, Type keyValueType) { Type[] keyValueTypes = keyValueType.GetGenericArguments(); Type keyType = keyValueTypes[0]; Type valueType = keyValueTypes[1]; int keyTypeNullableDepth = 0; Type keyTypeOriginal = keyType; while (keyType.IsGenericType && keyType.GetGenericTypeDefinition() == Globals.TypeOfNullable) { keyTypeNullableDepth++; keyType = keyType.GetGenericArguments()[0]; } ClassDataContract keyValueDataContract = (ClassDataContract)collectionContract.ItemContract; DataContract keyDataContract = keyValueDataContract.Members[0].MemberTypeContract; KeyParseMode keyParseMode = KeyParseMode.Fail; if (keyType == Globals.TypeOfString || keyType == Globals.TypeOfObject) { keyParseMode = KeyParseMode.AsString; } else if (keyType.IsEnum) { keyParseMode = KeyParseMode.UsingParseEnum; } else if (keyDataContract.ParseMethod != null) { keyParseMode = KeyParseMode.UsingCustomParse; } if (keyParseMode == KeyParseMode.Fail) { ThrowSerializationException( SR.Format( SR.KeyTypeCannotBeParsedInSimpleDictionary, DataContract.GetClrTypeFullName(collectionContract.UnderlyingType), DataContract.GetClrTypeFullName(keyType))); } else { LocalBuilder nodeType = _ilg.DeclareLocal(typeof(XmlNodeType), "nodeType"); _ilg.BeginWhileCondition(); _ilg.Call(_xmlReaderArg, JsonFormatGeneratorStatics.MoveToContentMethod); _ilg.Stloc(nodeType); _ilg.Load(nodeType); _ilg.Load(XmlNodeType.EndElement); _ilg.BeginWhileBody(Cmp.NotEqualTo); _ilg.Load(nodeType); _ilg.Load(XmlNodeType.Element); _ilg.If(Cmp.NotEqualTo); ThrowUnexpectedStateException(XmlNodeType.Element); _ilg.EndIf(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); if (keyParseMode == KeyParseMode.UsingParseEnum) { _ilg.Load(keyType); } _ilg.Load(_xmlReaderArg); _ilg.Call(JsonFormatGeneratorStatics.GetJsonMemberNameMethod); if (keyParseMode == KeyParseMode.UsingParseEnum) { _ilg.Call(JsonFormatGeneratorStatics.ParseEnumMethod); _ilg.ConvertValue(Globals.TypeOfObject, keyType); } else if (keyParseMode == KeyParseMode.UsingCustomParse) { _ilg.Call(keyDataContract.ParseMethod); } LocalBuilder pairKey = _ilg.DeclareLocal(keyType, "key"); _ilg.Stloc(pairKey); if (keyTypeNullableDepth > 0) { LocalBuilder pairKeyNullable = _ilg.DeclareLocal(keyTypeOriginal, "keyOriginal"); WrapNullableObject(pairKey, pairKeyNullable, keyTypeNullableDepth); pairKey = pairKeyNullable; } LocalBuilder pairValue = ReadValue(valueType, string.Empty); StoreKeyValuePair(_objectLocal, collectionContract, pairKey, pairValue); _ilg.EndWhile(); } }
void ReadSimpleDictionary(CollectionDataContract collectionContract, Type keyValueType) { Type[] keyValueTypes = keyValueType.GetGenericArguments(); Type keyType = keyValueTypes [0]; Type valueType = keyValueTypes [1]; int keyTypeNullableDepth = 0; Type keyTypeOriginal = keyType; while (keyType.IsGenericType && keyType.GetGenericTypeDefinition() == Globals.TypeOfNullable) { keyTypeNullableDepth++; keyType = keyType.GetGenericArguments() [0]; } ClassDataContract keyValueDataContract = (ClassDataContract)collectionContract.ItemContract; DataContract keyDataContract = keyValueDataContract.Members [0].MemberTypeContract; KeyParseMode keyParseMode = KeyParseMode.Fail; if (keyType == Globals.TypeOfString || keyType == Globals.TypeOfObject) { keyParseMode = KeyParseMode.AsString; } else if (keyType.IsEnum) { keyParseMode = KeyParseMode.UsingParseEnum; } else if (keyDataContract.ParseMethod != null) { keyParseMode = KeyParseMode.UsingCustomParse; } if (keyParseMode == KeyParseMode.Fail) { ThrowSerializationException( SR.GetString( SR.KeyTypeCannotBeParsedInSimpleDictionary, DataContract.GetClrTypeFullName(collectionContract.UnderlyingType), DataContract.GetClrTypeFullName(keyType))); } else { XmlNodeType nodeType; while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement) { if (nodeType != XmlNodeType.Element) { ThrowUnexpectedStateException(XmlNodeType.Element); } context.IncrementItemCount(1); var jsonMemberName = XmlObjectSerializerReadContextComplexJson.GetJsonMemberName(xmlReader); object key = null; if (keyParseMode == KeyParseMode.UsingParseEnum) { key = Enum.Parse(keyType, jsonMemberName); } else if (keyParseMode == KeyParseMode.UsingCustomParse) { key = keyDataContract.ParseMethod.Invoke(null, new object [] { jsonMemberName }); } if (keyTypeNullableDepth > 0) { var keyOriginal = WrapNullableObject(keyType, key, valueType, keyTypeNullableDepth); key = keyOriginal; } var value = ReadValue(valueType, String.Empty); collectionContract.AddMethod.Invoke(objectLocal, new object[] { key, value }); } } }