JsonCollectionDataContract.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //----------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //----------------------------------------------------------------
  4. namespace System.Runtime.Serialization.Json
  5. {
  6. using System.Threading;
  7. using System.Xml;
  8. using System.Security;
  9. class JsonCollectionDataContract : JsonDataContract
  10. {
  11. [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that is cached statically for serialization."
  12. + "Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
  13. [SecurityCritical]
  14. JsonCollectionDataContractCriticalHelper helper;
  15. [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
  16. Safe = "Doesn't leak anything.")]
  17. [SecuritySafeCritical]
  18. public JsonCollectionDataContract(CollectionDataContract traditionalDataContract)
  19. : base(new JsonCollectionDataContractCriticalHelper(traditionalDataContract))
  20. {
  21. this.helper = base.Helper as JsonCollectionDataContractCriticalHelper;
  22. }
  23. internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate
  24. {
  25. [Fx.Tag.SecurityNote(Critical = "Fetches the critical JsonFormatReaderDelegate property.",
  26. Safe = "JsonFormatReaderDelegate only needs to be protected for write.")]
  27. [SecuritySafeCritical]
  28. get
  29. {
  30. if (helper.JsonFormatReaderDelegate == null)
  31. {
  32. lock (this)
  33. {
  34. if (helper.JsonFormatReaderDelegate == null)
  35. {
  36. if (TraditionalCollectionDataContract.IsReadOnlyContract)
  37. {
  38. DataContract.ThrowInvalidDataContractException(TraditionalCollectionDataContract.DeserializationExceptionMessage, null /*type*/);
  39. }
  40. JsonFormatCollectionReaderDelegate tempDelegate = new JsonFormatReaderGenerator().GenerateCollectionReader(TraditionalCollectionDataContract);
  41. Thread.MemoryBarrier();
  42. helper.JsonFormatReaderDelegate = tempDelegate;
  43. }
  44. }
  45. }
  46. return helper.JsonFormatReaderDelegate;
  47. }
  48. }
  49. internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelegate
  50. {
  51. [Fx.Tag.SecurityNote(Critical = "Fetches the critical JsonFormatGetOnlyReaderDelegate property.",
  52. Safe = "JsonFormatGetOnlyReaderDelegate only needs to be protected for write; initialized in getter if null.")]
  53. [SecuritySafeCritical]
  54. get
  55. {
  56. if (helper.JsonFormatGetOnlyReaderDelegate == null)
  57. {
  58. lock (this)
  59. {
  60. if (helper.JsonFormatGetOnlyReaderDelegate == null)
  61. {
  62. CollectionKind kind = this.TraditionalCollectionDataContract.Kind;
  63. if (this.TraditionalDataContract.UnderlyingType.IsInterface && (kind == CollectionKind.Enumerable || kind == CollectionKind.Collection || kind == CollectionKind.GenericEnumerable))
  64. {
  65. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GetOnlyCollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(this.TraditionalDataContract.UnderlyingType))));
  66. }
  67. if (TraditionalCollectionDataContract.IsReadOnlyContract)
  68. {
  69. DataContract.ThrowInvalidDataContractException(TraditionalCollectionDataContract.DeserializationExceptionMessage, null /*type*/);
  70. }
  71. JsonFormatGetOnlyCollectionReaderDelegate tempDelegate = new JsonFormatReaderGenerator().GenerateGetOnlyCollectionReader(TraditionalCollectionDataContract);
  72. Thread.MemoryBarrier();
  73. helper.JsonFormatGetOnlyReaderDelegate = tempDelegate;
  74. }
  75. }
  76. }
  77. return helper.JsonFormatGetOnlyReaderDelegate;
  78. }
  79. }
  80. internal JsonFormatCollectionWriterDelegate JsonFormatWriterDelegate
  81. {
  82. [Fx.Tag.SecurityNote(Critical = "Fetches the critical JsonFormatWriterDelegate property.",
  83. Safe = "JsonFormatWriterDelegate only needs to be protected for write.")]
  84. [SecuritySafeCritical]
  85. get
  86. {
  87. if (helper.JsonFormatWriterDelegate == null)
  88. {
  89. lock (this)
  90. {
  91. if (helper.JsonFormatWriterDelegate == null)
  92. {
  93. JsonFormatCollectionWriterDelegate tempDelegate = new JsonFormatWriterGenerator().GenerateCollectionWriter(TraditionalCollectionDataContract);
  94. Thread.MemoryBarrier();
  95. helper.JsonFormatWriterDelegate = tempDelegate;
  96. }
  97. }
  98. }
  99. return helper.JsonFormatWriterDelegate;
  100. }
  101. }
  102. CollectionDataContract TraditionalCollectionDataContract
  103. {
  104. [Fx.Tag.SecurityNote(Critical = "Fetches the critical TraditionalCollectionDataContract property.",
  105. Safe = "TraditionalCollectionDataContract only needs to be protected for write.")]
  106. [SecuritySafeCritical]
  107. get { return this.helper.TraditionalCollectionDataContract; }
  108. }
  109. public override object ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
  110. {
  111. jsonReader.Read();
  112. object o = null;
  113. if (context.IsGetOnlyCollection)
  114. {
  115. // IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset.
  116. context.IsGetOnlyCollection = false;
  117. JsonFormatGetOnlyReaderDelegate(jsonReader, context, XmlDictionaryString.Empty, JsonGlobals.itemDictionaryString, TraditionalCollectionDataContract);
  118. }
  119. else
  120. {
  121. o = JsonFormatReaderDelegate(jsonReader, context, XmlDictionaryString.Empty, JsonGlobals.itemDictionaryString, TraditionalCollectionDataContract);
  122. }
  123. jsonReader.ReadEndElement();
  124. return o;
  125. }
  126. public override void WriteJsonValueCore(XmlWriterDelegator jsonWriter, object obj, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle)
  127. {
  128. // IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset.
  129. context.IsGetOnlyCollection = false;
  130. JsonFormatWriterDelegate(jsonWriter, obj, context, TraditionalCollectionDataContract);
  131. }
  132. [Fx.Tag.SecurityNote(Critical = "Holds all state used for (de)serializing types."
  133. + "Since the data is cached statically, we lock down access to it.")]
  134. #if !NO_SECURITY_ATTRIBUTES
  135. #pragma warning disable 618 // have not moved to the v4 security model yet
  136. [SecurityCritical(SecurityCriticalScope.Everything)]
  137. #pragma warning restore 618
  138. #endif
  139. class JsonCollectionDataContractCriticalHelper : JsonDataContractCriticalHelper
  140. {
  141. JsonFormatCollectionReaderDelegate jsonFormatReaderDelegate;
  142. JsonFormatGetOnlyCollectionReaderDelegate jsonFormatGetOnlyReaderDelegate;
  143. JsonFormatCollectionWriterDelegate jsonFormatWriterDelegate;
  144. CollectionDataContract traditionalCollectionDataContract;
  145. public JsonCollectionDataContractCriticalHelper(CollectionDataContract traditionalDataContract)
  146. : base(traditionalDataContract)
  147. {
  148. this.traditionalCollectionDataContract = traditionalDataContract;
  149. }
  150. internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate
  151. {
  152. get { return this.jsonFormatReaderDelegate; }
  153. set { this.jsonFormatReaderDelegate = value; }
  154. }
  155. internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelegate
  156. {
  157. get { return this.jsonFormatGetOnlyReaderDelegate; }
  158. set { this.jsonFormatGetOnlyReaderDelegate = value; }
  159. }
  160. internal JsonFormatCollectionWriterDelegate JsonFormatWriterDelegate
  161. {
  162. get { return this.jsonFormatWriterDelegate; }
  163. set { this.jsonFormatWriterDelegate = value; }
  164. }
  165. internal CollectionDataContract TraditionalCollectionDataContract
  166. {
  167. get { return this.traditionalCollectionDataContract; }
  168. }
  169. }
  170. }
  171. }