JsonFormatReaderGenerator_static.cs 26 KB

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