1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Reflection; 5 using System.Xml; 6 7 namespace System.Runtime.Serialization 8 { 9 internal partial class XmlFormatReaderGenerator 10 { 11 partial class CriticalHelper 12 { GenerateClassReader(ClassDataContract classContract)13 internal XmlFormatClassReaderDelegate GenerateClassReader(ClassDataContract classContract) 14 { 15 return (XmlReaderDelegator xr, XmlObjectSerializerReadContext ctx, XmlDictionaryString [] memberNames, XmlDictionaryString [] memberNamespaces) => new XmlFormatReaderInterpreter (classContract).ReadFromXml (xr, ctx, memberNames, memberNamespaces); 16 } 17 GenerateCollectionReader(CollectionDataContract collectionContract)18 internal XmlFormatCollectionReaderDelegate GenerateCollectionReader(CollectionDataContract collectionContract) 19 { 20 return (XmlReaderDelegator xr, XmlObjectSerializerReadContext ctx, XmlDictionaryString inm, XmlDictionaryString ins, CollectionDataContract cc) => new XmlFormatReaderInterpreter (collectionContract, false).ReadCollectionFromXml (xr, ctx, inm, ins, cc); 21 } 22 GenerateGetOnlyCollectionReader(CollectionDataContract collectionContract)23 internal XmlFormatGetOnlyCollectionReaderDelegate GenerateGetOnlyCollectionReader(CollectionDataContract collectionContract) 24 { 25 return (XmlReaderDelegator xr, XmlObjectSerializerReadContext ctx, XmlDictionaryString inm, XmlDictionaryString ins, CollectionDataContract cc) => new XmlFormatReaderInterpreter (collectionContract, true).ReadGetOnlyCollectionFromXml (xr, ctx, inm, ins, cc); 26 } 27 } 28 } 29 30 class XmlFormatReaderInterpreter 31 { XmlFormatReaderInterpreter(ClassDataContract classContract)32 public XmlFormatReaderInterpreter (ClassDataContract classContract) 33 { 34 this.classContract = classContract; 35 } 36 XmlFormatReaderInterpreter(CollectionDataContract collectionContract, bool isGetOnly)37 public XmlFormatReaderInterpreter (CollectionDataContract collectionContract, bool isGetOnly) 38 { 39 this.collectionContract = collectionContract; 40 this.is_get_only_collection = isGetOnly; 41 } 42 43 bool is_get_only_collection; 44 45 ClassDataContract classContract; 46 47 CollectionDataContract collectionContract; 48 49 object objectLocal; 50 Type objectType; 51 XmlReaderDelegator xmlReader; 52 XmlObjectSerializerReadContext context; 53 54 XmlDictionaryString [] memberNames = null; 55 XmlDictionaryString [] memberNamespaces = null; 56 XmlDictionaryString itemName = null; 57 XmlDictionaryString itemNamespace = null; 58 ReadFromXml(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces)59 public object ReadFromXml (XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces) 60 { 61 // InitArgs() 62 this.xmlReader = xmlReader; 63 this.context = context; 64 this.memberNames = memberNames; 65 this.memberNamespaces = memberNamespaces; 66 67 //DemandSerializationFormatterPermission(classContract); 68 //DemandMemberAccessPermission(memberAccessFlag); 69 CreateObject (classContract); 70 71 context.AddNewObject (objectLocal); 72 InvokeOnDeserializing (classContract); 73 74 string objectId = null; 75 76 if (HasFactoryMethod (classContract)) 77 objectId = context.GetObjectId (); 78 if (classContract.IsISerializable) 79 ReadISerializable (classContract); 80 else 81 ReadClass (classContract); 82 bool isFactoryType = InvokeFactoryMethod (classContract, objectId); 83 if (Globals.TypeOfIDeserializationCallback.IsAssignableFrom (classContract.UnderlyingType)) 84 ((IDeserializationCallback) objectLocal).OnDeserialization (null); 85 InvokeOnDeserialized(classContract); 86 if (objectId == null || !isFactoryType) { 87 88 // Do a conversion back from DateTimeOffsetAdapter to DateTimeOffset after deserialization. 89 // DateTimeOffsetAdapter is used here for deserialization purposes to bypass the ISerializable implementation 90 // on DateTimeOffset; which does not work in partial trust. 91 92 if (classContract.UnderlyingType == Globals.TypeOfDateTimeOffsetAdapter) 93 objectLocal = DateTimeOffsetAdapter.GetDateTimeOffset ((DateTimeOffsetAdapter) objectLocal); 94 // else - do we have to call CodeInterpreter.ConvertValue()? I guess not... 95 } 96 return objectLocal; 97 } 98 ReadCollectionFromXml(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract)99 public object ReadCollectionFromXml (XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract) 100 { 101 #region GenerateCollectionReaderHelper 102 // InitArgs() 103 this.xmlReader = xmlReader; 104 this.context = context; 105 this.itemName = itemName; 106 this.itemNamespace = itemNamespace; 107 108 this.collectionContract = collectionContract; 109 110 #endregion 111 112 ReadCollection (collectionContract); 113 114 return objectLocal; 115 } 116 ReadGetOnlyCollectionFromXml(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract)117 public void ReadGetOnlyCollectionFromXml (XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract) 118 { 119 #region GenerateCollectionReaderHelper 120 // InitArgs() 121 this.xmlReader = xmlReader; 122 this.context = context; 123 this.itemName = itemName; 124 this.itemNamespace = itemNamespace; 125 126 this.collectionContract = collectionContract; 127 128 #endregion 129 130 ReadGetOnlyCollection (collectionContract); 131 } 132 CreateObject(ClassDataContract classContract)133 void CreateObject (ClassDataContract classContract) 134 { 135 Type type = objectType = classContract.UnderlyingType; 136 if (type.IsValueType && !classContract.IsNonAttributedType) 137 type = Globals.TypeOfValueType; 138 139 if (classContract.UnderlyingType == Globals.TypeOfDBNull) 140 objectLocal = DBNull.Value; 141 else if (classContract.IsNonAttributedType) { 142 if (type.IsValueType) 143 objectLocal = FormatterServices.GetUninitializedObject (type); 144 else 145 objectLocal = classContract.GetNonAttributedTypeConstructor ().Invoke (new object [0]); 146 } 147 else 148 objectLocal = CodeInterpreter.ConvertValue (XmlFormatReaderGenerator.UnsafeGetUninitializedObject (DataContract.GetIdForInitialization (classContract)), Globals.TypeOfObject, type); 149 } 150 InvokeOnDeserializing(ClassDataContract classContract)151 void InvokeOnDeserializing (ClassDataContract classContract) 152 { 153 if (classContract.BaseContract != null) 154 InvokeOnDeserializing (classContract.BaseContract); 155 if (classContract.OnDeserializing != null) 156 classContract.OnDeserializing.Invoke (objectLocal, new object [] {context.GetStreamingContext ()}); 157 } 158 InvokeOnDeserialized(ClassDataContract classContract)159 void InvokeOnDeserialized (ClassDataContract classContract) 160 { 161 if (classContract.BaseContract != null) 162 InvokeOnDeserialized (classContract.BaseContract); 163 if (classContract.OnDeserialized != null) 164 classContract.OnDeserialized.Invoke (objectLocal, new object [] {context.GetStreamingContext ()}); 165 } 166 HasFactoryMethod(ClassDataContract classContract)167 bool HasFactoryMethod (ClassDataContract classContract) 168 { 169 return Globals.TypeOfIObjectReference.IsAssignableFrom (classContract.UnderlyingType); 170 } 171 InvokeFactoryMethod(ClassDataContract classContract, string objectId)172 bool InvokeFactoryMethod (ClassDataContract classContract, string objectId) 173 { 174 if (HasFactoryMethod (classContract)) { 175 objectLocal = CodeInterpreter.ConvertValue (context.GetRealObject ((IObjectReference) objectLocal, objectId), Globals.TypeOfObject, classContract.UnderlyingType); 176 return true; 177 } 178 return false; 179 } 180 ReadISerializable(ClassDataContract classContract)181 void ReadISerializable (ClassDataContract classContract) 182 { 183 ConstructorInfo ctor = classContract.GetISerializableConstructor (); 184 var info = context.ReadSerializationInfo (xmlReader, classContract.UnderlyingType); 185 ctor.Invoke (objectLocal, new object [] {info, context.GetStreamingContext ()}); 186 } 187 ReadClass(ClassDataContract classContract)188 void ReadClass (ClassDataContract classContract) 189 { 190 if (classContract.HasExtensionData) { 191 ExtensionDataObject extensionData = new ExtensionDataObject (); 192 ReadMembers (classContract, extensionData); 193 ClassDataContract currentContract = classContract; 194 while (currentContract != null) { 195 MethodInfo extensionDataSetMethod = currentContract.ExtensionDataSetMethod; 196 if (extensionDataSetMethod != null) 197 extensionDataSetMethod.Invoke (objectLocal, new object [] {extensionData}); 198 currentContract = currentContract.BaseContract; 199 } 200 } 201 else 202 ReadMembers (classContract, null); 203 } 204 ReadMembers(ClassDataContract classContract, ExtensionDataObject extensionData)205 void ReadMembers (ClassDataContract classContract, ExtensionDataObject extensionData) 206 { 207 int memberCount = classContract.MemberNames.Length; 208 context.IncrementItemCount (memberCount); 209 210 int memberIndex = -1; 211 212 int firstRequiredMember; 213 bool[] requiredMembers = GetRequiredMembers (classContract, out firstRequiredMember); 214 bool hasRequiredMembers = (firstRequiredMember < memberCount); 215 int requiredIndex = hasRequiredMembers ? firstRequiredMember : memberCount; 216 217 while (XmlObjectSerializerReadContext.MoveToNextElement (xmlReader)) { 218 int idx; // used as in "switch (idx)" in the original source. 219 if (hasRequiredMembers) 220 idx = context.GetMemberIndexWithRequiredMembers (xmlReader, memberNames, memberNamespaces, memberIndex, (int) requiredIndex, extensionData); 221 else 222 idx = context.GetMemberIndex (xmlReader, memberNames, memberNamespaces, memberIndex, extensionData); 223 224 if (memberCount > 0) 225 ReadMembers (idx, classContract, requiredMembers, ref memberIndex, ref requiredIndex); 226 } 227 228 if (hasRequiredMembers) 229 { 230 if (requiredIndex < memberCount) 231 XmlObjectSerializerReadContext.ThrowRequiredMemberMissingException (xmlReader, memberIndex, requiredIndex, memberNames); 232 } 233 } 234 ReadMembers(int index, ClassDataContract classContract, bool [] requiredMembers, ref int memberIndex, ref int requiredIndex)235 int ReadMembers (int index, ClassDataContract classContract, bool [] requiredMembers, ref int memberIndex, ref int requiredIndex) 236 { 237 int memberCount = (classContract.BaseContract == null) ? 0 : ReadMembers (index, classContract.BaseContract, requiredMembers, 238 ref memberIndex, ref requiredIndex); 239 240 if (memberCount <= index && index < memberCount + classContract.Members.Count) { 241 DataMember dataMember = classContract.Members [index - memberCount]; 242 Type memberType = dataMember.MemberType; 243 if (dataMember.IsRequired) { 244 int nextRequiredIndex = index + 1; 245 for (; nextRequiredIndex < requiredMembers.Length; nextRequiredIndex++) 246 if (requiredMembers [nextRequiredIndex]) 247 break; 248 requiredIndex = nextRequiredIndex; 249 } 250 251 if (dataMember.IsGetOnlyCollection) { 252 var value = CodeInterpreter.GetMember (dataMember.MemberInfo, objectLocal); 253 context.StoreCollectionMemberInfo (value); 254 ReadValue (memberType, dataMember.Name, classContract.StableName.Namespace); 255 } else { 256 var value = ReadValue (memberType, dataMember.Name, classContract.StableName.Namespace); 257 CodeInterpreter.SetMember (dataMember.MemberInfo, objectLocal, value); 258 } 259 memberIndex = index; 260 } 261 return memberCount + classContract.Members.Count; 262 } 263 GetRequiredMembers(ClassDataContract contract, out int firstRequiredMember)264 bool[] GetRequiredMembers (ClassDataContract contract, out int firstRequiredMember) 265 { 266 int memberCount = contract.MemberNames.Length; 267 bool [] requiredMembers = new bool [memberCount]; 268 GetRequiredMembers (contract, requiredMembers); 269 for (firstRequiredMember = 0; firstRequiredMember < memberCount; firstRequiredMember++) 270 if (requiredMembers [firstRequiredMember]) 271 break; 272 return requiredMembers; 273 } 274 GetRequiredMembers(ClassDataContract contract, bool[] requiredMembers)275 int GetRequiredMembers (ClassDataContract contract, bool[] requiredMembers) 276 { 277 int memberCount = (contract.BaseContract == null) ? 0 : GetRequiredMembers (contract.BaseContract, requiredMembers); 278 List<DataMember> members = contract.Members; 279 for (int i = 0; i < members.Count; i++, memberCount++) 280 requiredMembers [memberCount] = members [i].IsRequired; 281 return memberCount; 282 } 283 ReadValue(Type type, string name, string ns)284 object ReadValue (Type type, string name, string ns) 285 { 286 var valueType = type; 287 object value = null; 288 bool shouldAssignNullableValue = false; 289 int nullables = 0; 290 while (type.IsGenericType && type.GetGenericTypeDefinition () == Globals.TypeOfNullable) { 291 nullables++; 292 type = type.GetGenericArguments () [0]; 293 } 294 295 PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract (type); 296 if ((primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) || nullables != 0 || type.IsValueType) { 297 context.ReadAttributes (xmlReader); 298 string objectId = context.ReadIfNullOrRef (xmlReader, type, DataContract.IsTypeSerializable (type)); 299 // Deserialize null 300 if (objectId == Globals.NullObjectId) { 301 302 if (nullables != 0) 303 value = Activator.CreateInstance (valueType); 304 else if (type.IsValueType) 305 throw new SerializationException (SR.GetString (SR.ValueTypeCannotBeNull, DataContract.GetClrTypeFullName (type))); 306 else 307 value = null; 308 } else if (objectId == string.Empty) { 309 // Deserialize value 310 311 // Compare against Globals.NewObjectId, which is set to string.Empty 312 313 objectId = context.GetObjectId (); 314 315 if (type.IsValueType) { 316 if (!string.IsNullOrEmpty (objectId)) 317 throw new SerializationException (SR.GetString (SR.ValueTypeCannotHaveId, DataContract.GetClrTypeFullName(type))); 318 } 319 object innerValueRead = null; 320 if (nullables != 0) 321 shouldAssignNullableValue = true; 322 323 if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) { 324 value = primitiveContract.XmlFormatReaderMethod.Invoke (xmlReader, new object [0]); 325 if (!type.IsValueType) 326 context.AddNewObject (value); 327 } 328 else 329 value = InternalDeserialize (type, name, ns); 330 } else { 331 // Deserialize ref 332 if (type.IsValueType) 333 throw new SerializationException (SR.GetString (SR.ValueTypeCannotHaveRef, DataContract.GetClrTypeFullName (type))); 334 else 335 value = CodeInterpreter.ConvertValue (context.GetExistingObject (objectId, type, name, ns), Globals.TypeOfObject, type); 336 } 337 338 if (shouldAssignNullableValue) { 339 if (objectId != Globals.NullObjectId) 340 value = WrapNullableObject (type, value, valueType, nullables); 341 } 342 } 343 else 344 value = InternalDeserialize (type, name, ns); 345 346 return value; 347 } 348 InternalDeserialize(Type type, string name, string ns)349 object InternalDeserialize (Type type, string name, string ns) 350 { 351 Type declaredType = type.IsPointer ? Globals.TypeOfReflectionPointer : type; 352 var obj = context.InternalDeserialize (xmlReader, DataContract.GetId (declaredType.TypeHandle), declaredType.TypeHandle, name, ns); 353 354 if (type.IsPointer) 355 // wow, there is no way to convert void* to object in strongly typed way... 356 return XmlFormatGeneratorStatics.UnboxPointer.Invoke (null, new object [] {obj}); 357 else 358 return CodeInterpreter.ConvertValue (obj, Globals.TypeOfObject, type); 359 } 360 WrapNullableObject(Type innerType, object innerValue, Type outerType, int nullables)361 object WrapNullableObject (Type innerType, object innerValue, Type outerType, int nullables) 362 { 363 var outerValue = innerValue; 364 for (int i = 1; i < nullables; i++) { 365 Type type = Globals.TypeOfNullable.MakeGenericType (innerType); 366 outerValue = Activator.CreateInstance (type, new object[] { outerValue }); 367 innerType = type; 368 } 369 return Activator.CreateInstance (outerType, new object[] { outerValue }); 370 } 371 372 ReadCollection(CollectionDataContract collectionContract)373 void ReadCollection (CollectionDataContract collectionContract) 374 { 375 Type type = collectionContract.UnderlyingType; 376 Type itemType = collectionContract.ItemType; 377 bool isArray = (collectionContract.Kind == CollectionKind.Array); 378 379 ConstructorInfo constructor = collectionContract.Constructor; 380 381 if (type.IsInterface) { 382 switch (collectionContract.Kind) { 383 case CollectionKind.GenericDictionary: 384 type = Globals.TypeOfDictionaryGeneric.MakeGenericType (itemType.GetGenericArguments ()); 385 constructor = type.GetConstructor (BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); 386 break; 387 case CollectionKind.Dictionary: 388 type = Globals.TypeOfHashtable; 389 constructor = XmlFormatGeneratorStatics.HashtableCtor; 390 break; 391 case CollectionKind.Collection: 392 case CollectionKind.GenericCollection: 393 case CollectionKind.Enumerable: 394 case CollectionKind.GenericEnumerable: 395 case CollectionKind.List: 396 case CollectionKind.GenericList: 397 type = itemType.MakeArrayType (); 398 isArray = true; 399 break; 400 } 401 } 402 string itemName = collectionContract.ItemName; 403 string itemNs = collectionContract.StableName.Namespace; 404 405 if (!isArray) { 406 if (type.IsValueType) 407 // FIXME: this is not what the original code does. 408 objectLocal = FormatterServices.GetUninitializedObject (type); 409 else { 410 objectLocal = constructor.Invoke (new object [0]); 411 context.AddNewObject (objectLocal); 412 } 413 } 414 415 int size = context.GetArraySize (); 416 417 string objectId = context.GetObjectId (); 418 419 bool canReadPrimitiveArray = false, readResult = false; 420 if (isArray && TryReadPrimitiveArray (type, itemType, size, out readResult)) 421 canReadPrimitiveArray = true; 422 423 if (!readResult) { 424 if (size == -1) { 425 426 object growingCollection = null; 427 if (isArray) 428 growingCollection = Array.CreateInstance (itemType, 32); 429 430 int i = 0; 431 // FIXME: I cannot find i++ part, but without that it won't work as expected. 432 for (; i < int.MaxValue; i++) { 433 if (IsStartElement (this.itemName, this.itemNamespace)) { 434 context.IncrementItemCount (1); 435 object value = ReadCollectionItem (collectionContract, itemType, itemName, itemNs); 436 if (isArray) { 437 MethodInfo ensureArraySizeMethod = XmlFormatGeneratorStatics.EnsureArraySizeMethod.MakeGenericMethod (itemType); 438 growingCollection = ensureArraySizeMethod.Invoke (null, new object [] {growingCollection, i}); 439 ((Array) growingCollection).SetValue (value, i); 440 } else { 441 StoreCollectionValue (objectLocal, itemType, value, collectionContract); 442 } 443 } 444 else if (IsEndElement ()) 445 break; 446 else 447 HandleUnexpectedItemInCollection (ref i); 448 } 449 450 if (isArray) { 451 MethodInfo trimArraySizeMethod = XmlFormatGeneratorStatics.TrimArraySizeMethod.MakeGenericMethod (itemType); 452 objectLocal = trimArraySizeMethod.Invoke (null, new object [] {growingCollection, i}); 453 context.AddNewObjectWithId (objectId, objectLocal); 454 } 455 } else { 456 context.IncrementItemCount (size); 457 if (isArray) { 458 objectLocal = Array.CreateInstance (itemType, size); 459 context.AddNewObject (objectLocal); 460 } 461 // FIXME: I cannot find j++ part, but without that it won't work as expected. 462 for (int j = 0; j < size; j++) { 463 if (IsStartElement (this.itemName, this.itemNamespace)) { 464 var itemValue = ReadCollectionItem (collectionContract, itemType, itemName, itemNs); 465 if (isArray) 466 ((Array) objectLocal).SetValue (itemValue, j); 467 else 468 StoreCollectionValue (objectLocal, itemType, itemValue, collectionContract); 469 } 470 else 471 HandleUnexpectedItemInCollection (ref j); 472 } 473 context.CheckEndOfArray (xmlReader, size, this.itemName, this.itemNamespace); 474 } 475 } 476 if (canReadPrimitiveArray) 477 context.AddNewObjectWithId (objectId, objectLocal); 478 } 479 ReadGetOnlyCollection(CollectionDataContract collectionContract)480 void ReadGetOnlyCollection (CollectionDataContract collectionContract) 481 { 482 Type type = collectionContract.UnderlyingType; 483 Type itemType = collectionContract.ItemType; 484 bool isArray = (collectionContract.Kind == CollectionKind.Array); 485 string itemName = collectionContract.ItemName; 486 string itemNs = collectionContract.StableName.Namespace; 487 488 objectLocal = context.GetCollectionMember (); 489 490 //check that items are actually going to be deserialized into the collection 491 if (IsStartElement (this.itemName, this.itemNamespace)) { 492 if (objectLocal == null) 493 XmlObjectSerializerReadContext.ThrowNullValueReturnedForGetOnlyCollectionException (type); 494 else { 495 int size = 0; 496 if (isArray) 497 size = ((Array) objectLocal).Length; 498 context.AddNewObject (objectLocal); 499 for (int i = 0; i < int.MaxValue;) { 500 if (IsStartElement (this.itemName, this.itemNamespace)) { 501 context.IncrementItemCount (1); 502 var value = ReadCollectionItem (collectionContract, itemType, itemName, itemNs); 503 if (isArray) { 504 if (size == i) 505 XmlObjectSerializerReadContext.ThrowArrayExceededSizeException (size, type); 506 else 507 ((Array) objectLocal).SetValue (value, i); 508 } else { 509 StoreCollectionValue (objectLocal, itemType, value, collectionContract); 510 } 511 } 512 else if (IsEndElement()) 513 break; 514 else 515 HandleUnexpectedItemInCollection (ref i); 516 } 517 context.CheckEndOfArray (xmlReader, size, this.itemName, this.itemNamespace); 518 } 519 } 520 } 521 TryReadPrimitiveArray(Type type, Type itemType, int size, out bool readResult)522 bool TryReadPrimitiveArray (Type type, Type itemType, int size, out bool readResult) 523 { 524 readResult = false; 525 PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract (itemType); 526 if (primitiveContract == null) 527 return false; 528 529 string readArrayMethod = null; 530 switch (Type.GetTypeCode (itemType)) 531 { 532 case TypeCode.Boolean: 533 readArrayMethod = "TryReadBooleanArray"; 534 break; 535 case TypeCode.DateTime: 536 readArrayMethod = "TryReadDateTimeArray"; 537 break; 538 case TypeCode.Decimal: 539 readArrayMethod = "TryReadDecimalArray"; 540 break; 541 case TypeCode.Int32: 542 readArrayMethod = "TryReadInt32Array"; 543 break; 544 case TypeCode.Int64: 545 readArrayMethod = "TryReadInt64Array"; 546 break; 547 case TypeCode.Single: 548 readArrayMethod = "TryReadSingleArray"; 549 break; 550 case TypeCode.Double: 551 readArrayMethod = "TryReadDoubleArray"; 552 break; 553 default: 554 break; 555 } 556 if (readArrayMethod != null) { 557 var mi = typeof (XmlReaderDelegator).GetMethod (readArrayMethod, Globals.ScanAllMembers); 558 var args = new object [] {context, itemName, itemNamespace, size, objectLocal}; 559 readResult = (bool) mi.Invoke (xmlReader, args); 560 objectLocal = args.Last (); 561 return true; 562 } 563 return false; 564 } 565 ReadCollectionItem(CollectionDataContract collectionContract, Type itemType, string itemName, string itemNs)566 object ReadCollectionItem (CollectionDataContract collectionContract, Type itemType, string itemName, string itemNs) 567 { 568 if (collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary) { 569 context.ResetAttributes (); 570 return CodeInterpreter.ConvertValue (collectionContract.ItemContract.ReadXmlValue (xmlReader, context), Globals.TypeOfObject, itemType); 571 } 572 else 573 return ReadValue (itemType, itemName, itemNs); 574 } 575 StoreCollectionValue(object collection, Type valueType, object value, CollectionDataContract collectionContract)576 void StoreCollectionValue (object collection, Type valueType, object value, CollectionDataContract collectionContract) 577 { 578 if (collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary) { 579 ClassDataContract keyValuePairContract = DataContract.GetDataContract (valueType) as ClassDataContract; 580 if (keyValuePairContract == null) 581 Fx.Assert ("Failed to create contract for KeyValuePair type"); 582 DataMember keyMember = keyValuePairContract.Members [0]; 583 DataMember valueMember = keyValuePairContract.Members [1]; 584 object pkey = CodeInterpreter.GetMember (keyMember.MemberInfo, value); 585 object pvalue = CodeInterpreter.GetMember (valueMember.MemberInfo, value); 586 587 collectionContract.AddMethod.Invoke (collection, new object [] {pkey, pvalue}); 588 } 589 else 590 collectionContract.AddMethod.Invoke (collection, new object [] {value}); 591 } 592 HandleUnexpectedItemInCollection(ref int iterator)593 void HandleUnexpectedItemInCollection (ref int iterator) 594 { 595 if (IsStartElement ()) { 596 context.SkipUnknownElement (xmlReader); 597 iterator--; 598 } 599 else 600 throw XmlObjectSerializerReadContext.CreateUnexpectedStateException (XmlNodeType.Element, xmlReader); 601 } 602 IsStartElement(XmlDictionaryString name, XmlDictionaryString ns)603 bool IsStartElement(XmlDictionaryString name, XmlDictionaryString ns) 604 { 605 return xmlReader.IsStartElement (name, ns); 606 } 607 IsStartElement()608 bool IsStartElement() 609 { 610 return xmlReader.IsStartElement (); 611 } 612 IsEndElement()613 bool IsEndElement () 614 { 615 return xmlReader.NodeType == XmlNodeType.EndElement; 616 } 617 } 618 } 619