ClassDataContract.cs 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.Runtime.Serialization
  5. {
  6. using System;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using System.Reflection;
  10. using System.Security;
  11. using System.Threading;
  12. using System.Xml;
  13. using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, DataContract>;
  14. #if USE_REFEMIT
  15. public sealed class ClassDataContract : DataContract
  16. #else
  17. internal sealed class ClassDataContract : DataContract
  18. #endif
  19. {
  20. [Fx.Tag.SecurityNote(Miscellaneous =
  21. "RequiresReview - XmlDictionaryString(s) representing the XML namespaces for class members."
  22. + "statically cached and used from IL generated code. should ideally be Critical."
  23. + "marked SecurityNode to be callable from transparent IL generated code."
  24. + "not changed to property to avoid regressing performance; any changes to initalization should be reviewed.")]
  25. public XmlDictionaryString[] ContractNamespaces;
  26. [Fx.Tag.SecurityNote(Miscellaneous =
  27. "RequiresReview - XmlDictionaryString(s) representing the XML element names for class members."
  28. + "statically cached and used from IL generated code. should ideally be Critical."
  29. + "marked SecurityNode to be callable from transparent IL generated code."
  30. + "not changed to property to avoid regressing performance; any changes to initalization should be reviewed.")]
  31. public XmlDictionaryString[] MemberNames;
  32. [Fx.Tag.SecurityNote(Miscellaneous =
  33. "RequiresReview - XmlDictionaryString(s) representing the XML namespaces for class members."
  34. + "statically cached and used from IL generated code. should ideally be Critical."
  35. + "marked SecurityNode to be callable from transparent IL generated code."
  36. + "not changed to property to avoid regressing performance; any changes to initalization should be reviewed.")]
  37. public XmlDictionaryString[] MemberNamespaces;
  38. [Fx.Tag.SecurityNote(Critical = "XmlDictionaryString representing the XML namespaces for members of class."
  39. + "Statically cached and used from IL generated code.")]
  40. #if !NO_SECURITY_ATTRIBUTES
  41. [SecurityCritical]
  42. #endif
  43. XmlDictionaryString[] childElementNamespaces;
  44. [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that is cached statically for serialization. "
  45. + "Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
  46. #if !NO_SECURITY_ATTRIBUTES
  47. [SecurityCritical]
  48. #endif
  49. ClassDataContractCriticalHelper helper;
  50. [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'",
  51. Safe = "Doesn't leak anything.")]
  52. [SecuritySafeCritical]
  53. internal ClassDataContract()
  54. : base(new ClassDataContractCriticalHelper())
  55. {
  56. InitClassDataContract();
  57. }
  58. [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'",
  59. Safe = "Doesn't leak anything.")]
  60. #if !NO_SECURITY_ATTRIBUTES
  61. [SecuritySafeCritical]
  62. #endif
  63. internal ClassDataContract(Type type)
  64. : base(new ClassDataContractCriticalHelper(type))
  65. {
  66. InitClassDataContract();
  67. }
  68. [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'",
  69. Safe = "Doesn't leak anything.")]
  70. #if !NO_SECURITY_ATTRIBUTES
  71. [SecuritySafeCritical]
  72. #endif
  73. ClassDataContract(Type type, XmlDictionaryString ns, string[] memberNames)
  74. : base(new ClassDataContractCriticalHelper(type, ns, memberNames))
  75. {
  76. InitClassDataContract();
  77. }
  78. [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical fields; called from all constructors.")]
  79. #if !NO_SECURITY_ATTRIBUTES
  80. [SecurityCritical]
  81. #endif
  82. void InitClassDataContract()
  83. {
  84. this.helper = base.Helper as ClassDataContractCriticalHelper;
  85. this.ContractNamespaces = helper.ContractNamespaces;
  86. this.MemberNames = helper.MemberNames;
  87. this.MemberNamespaces = helper.MemberNamespaces;
  88. }
  89. internal ClassDataContract BaseContract
  90. {
  91. [Fx.Tag.SecurityNote(Critical = "Fetches the critical baseContract property.",
  92. Safe = "baseContract only needs to be protected for write.")]
  93. [SecuritySafeCritical]
  94. get { return helper.BaseContract; }
  95. [Fx.Tag.SecurityNote(Critical = "Sets the critical baseContract property.")]
  96. [SecurityCritical]
  97. set { helper.BaseContract = value; }
  98. }
  99. internal List<DataMember> Members
  100. {
  101. [Fx.Tag.SecurityNote(Critical = "Fetches the critical members property.",
  102. Safe = "members only needs to be protected for write.")]
  103. [SecuritySafeCritical]
  104. get { return helper.Members; }
  105. [Fx.Tag.SecurityNote(Critical = "Sets the critical members property.",
  106. Safe = "Protected for write if contract has underlyingType.")]
  107. [SecurityCritical]
  108. set { helper.Members = value; }
  109. }
  110. public XmlDictionaryString[] ChildElementNamespaces
  111. {
  112. [Fx.Tag.SecurityNote(Critical = "Sets the critical childElementNamespaces property.",
  113. Safe = "childElementNamespaces only needs to be protected for write; initialized in getter if null.")]
  114. [SecuritySafeCritical]
  115. get
  116. {
  117. if (this.childElementNamespaces == null)
  118. {
  119. lock (this)
  120. {
  121. if (this.childElementNamespaces == null)
  122. {
  123. if (helper.ChildElementNamespaces == null)
  124. {
  125. XmlDictionaryString[] tempChildElementamespaces = CreateChildElementNamespaces();
  126. Thread.MemoryBarrier();
  127. helper.ChildElementNamespaces = tempChildElementamespaces;
  128. }
  129. this.childElementNamespaces = helper.ChildElementNamespaces;
  130. }
  131. }
  132. }
  133. return this.childElementNamespaces;
  134. }
  135. }
  136. internal MethodInfo OnSerializing
  137. {
  138. [Fx.Tag.SecurityNote(Critical = "Fetches the critical onSerializing property.",
  139. Safe = "onSerializing only needs to be protected for write.")]
  140. [SecuritySafeCritical]
  141. get { return helper.OnSerializing; }
  142. }
  143. internal MethodInfo OnSerialized
  144. {
  145. [Fx.Tag.SecurityNote(Critical = "Fetches the critical onSerialized property.",
  146. Safe = "onSerialized only needs to be protected for write.")]
  147. [SecuritySafeCritical]
  148. get { return helper.OnSerialized; }
  149. }
  150. internal MethodInfo OnDeserializing
  151. {
  152. [Fx.Tag.SecurityNote(Critical = "Fetches the critical onDeserializing property.",
  153. Safe = "onDeserializing only needs to be protected for write.")]
  154. [SecuritySafeCritical]
  155. get { return helper.OnDeserializing; }
  156. }
  157. internal MethodInfo OnDeserialized
  158. {
  159. [Fx.Tag.SecurityNote(Critical = "Fetches the critical onDeserialized property.",
  160. Safe = "onDeserialized only needs to be protected for write.")]
  161. [SecuritySafeCritical]
  162. get { return helper.OnDeserialized; }
  163. }
  164. internal MethodInfo ExtensionDataSetMethod
  165. {
  166. [Fx.Tag.SecurityNote(Critical = "Fetches the critical extensionDataSetMethod property.",
  167. Safe = "extensionDataSetMethod only needs to be protected for write.")]
  168. [SecuritySafeCritical]
  169. get { return helper.ExtensionDataSetMethod; }
  170. }
  171. internal override DataContractDictionary KnownDataContracts
  172. {
  173. [Fx.Tag.SecurityNote(Critical = "Fetches the critical knownDataContracts property.",
  174. Safe = "knownDataContracts only needs to be protected for write.")]
  175. [SecuritySafeCritical]
  176. get { return helper.KnownDataContracts; }
  177. [Fx.Tag.SecurityNote(Critical = "Sets the critical knownDataContracts property.",
  178. Safe = "Protected for write if contract has underlyingType.")]
  179. [SecurityCritical]
  180. set { helper.KnownDataContracts = value; }
  181. }
  182. internal override bool IsISerializable
  183. {
  184. [Fx.Tag.SecurityNote(Critical = "Fetches the critical isISerializable property.",
  185. Safe = "isISerializable only needs to be protected for write.")]
  186. [SecuritySafeCritical]
  187. get { return helper.IsISerializable; }
  188. [Fx.Tag.SecurityNote(Critical = "Sets the critical isISerializable property.",
  189. Safe = "Protected for write if contract has underlyingType.")]
  190. [SecurityCritical]
  191. set { helper.IsISerializable = value; }
  192. }
  193. internal bool IsNonAttributedType
  194. {
  195. [Fx.Tag.SecurityNote(Critical = "Fetches the critical IsNonAttributedType property.",
  196. Safe = "IsNonAttributedType only needs to be protected for write.")]
  197. [SecuritySafeCritical]
  198. get { return helper.IsNonAttributedType; }
  199. }
  200. internal bool HasDataContract
  201. {
  202. [Fx.Tag.SecurityNote(Critical = "Fetches the critical hasDataContract property.",
  203. Safe = "hasDataContract only needs to be protected for write.")]
  204. [SecuritySafeCritical]
  205. get { return helper.HasDataContract; }
  206. }
  207. internal bool HasExtensionData
  208. {
  209. [Fx.Tag.SecurityNote(Critical = "Fetches the critical hasExtensionData property.",
  210. Safe = "hasExtensionData only needs to be protected for write.")]
  211. [SecuritySafeCritical]
  212. get { return helper.HasExtensionData; }
  213. }
  214. internal string SerializationExceptionMessage
  215. {
  216. [Fx.Tag.SecurityNote(Critical = "Fetches the critical serializationExceptionMessage property.",
  217. Safe = "serializationExceptionMessage only needs to be protected for write.")]
  218. [SecuritySafeCritical]
  219. get { return helper.SerializationExceptionMessage; }
  220. }
  221. internal string DeserializationExceptionMessage
  222. {
  223. [Fx.Tag.SecurityNote(Critical = "Fetches the critical deserializationExceptionMessage property.",
  224. Safe = "deserializationExceptionMessage only needs to be protected for write.")]
  225. [SecuritySafeCritical]
  226. get { return helper.DeserializationExceptionMessage; }
  227. }
  228. internal bool IsReadOnlyContract
  229. {
  230. get { return this.DeserializationExceptionMessage != null; }
  231. }
  232. [Fx.Tag.SecurityNote(Critical = "Fetches information about which constructor should be used to initialize ISerializable types.",
  233. Safe = "only needs to be protected for write.")]
  234. [SecuritySafeCritical]
  235. internal ConstructorInfo GetISerializableConstructor()
  236. {
  237. return helper.GetISerializableConstructor();
  238. }
  239. [Fx.Tag.SecurityNote(Critical = "Fetches information about which constructor should be used to initialize non-attributed types that are valid for serialization.",
  240. Safe = "only needs to be protected for write.")]
  241. [SecuritySafeCritical]
  242. internal ConstructorInfo GetNonAttributedTypeConstructor()
  243. {
  244. return helper.GetNonAttributedTypeConstructor();
  245. }
  246. internal XmlFormatClassWriterDelegate XmlFormatWriterDelegate
  247. {
  248. [Fx.Tag.SecurityNote(Critical = "Fetches the critical xmlFormatWriterDelegate property.",
  249. Safe = "xmlFormatWriterDelegate only needs to be protected for write; initialized in getter if null.")]
  250. [SecuritySafeCritical]
  251. get
  252. {
  253. if (helper.XmlFormatWriterDelegate == null)
  254. {
  255. lock (this)
  256. {
  257. if (helper.XmlFormatWriterDelegate == null)
  258. {
  259. XmlFormatClassWriterDelegate tempDelegate = new XmlFormatWriterGenerator().GenerateClassWriter(this);
  260. Thread.MemoryBarrier();
  261. helper.XmlFormatWriterDelegate = tempDelegate;
  262. }
  263. }
  264. }
  265. return helper.XmlFormatWriterDelegate;
  266. }
  267. }
  268. internal XmlFormatClassReaderDelegate XmlFormatReaderDelegate
  269. {
  270. [Fx.Tag.SecurityNote(Critical = "Fetches the critical xmlFormatReaderDelegate property.",
  271. Safe = "xmlFormatReaderDelegate only needs to be protected for write; initialized in getter if null.")]
  272. [SecuritySafeCritical]
  273. get
  274. {
  275. if (helper.XmlFormatReaderDelegate == null)
  276. {
  277. lock (this)
  278. {
  279. if (helper.XmlFormatReaderDelegate == null)
  280. {
  281. if (this.IsReadOnlyContract)
  282. {
  283. ThrowInvalidDataContractException(helper.DeserializationExceptionMessage, null /*type*/);
  284. }
  285. XmlFormatClassReaderDelegate tempDelegate = new XmlFormatReaderGenerator().GenerateClassReader(this);
  286. Thread.MemoryBarrier();
  287. helper.XmlFormatReaderDelegate = tempDelegate;
  288. }
  289. }
  290. }
  291. return helper.XmlFormatReaderDelegate;
  292. }
  293. }
  294. internal static ClassDataContract CreateClassDataContractForKeyValue(Type type, XmlDictionaryString ns, string[] memberNames)
  295. {
  296. return new ClassDataContract(type, ns, memberNames);
  297. }
  298. internal static void CheckAndAddMember(List<DataMember> members, DataMember memberContract, Dictionary<string, DataMember> memberNamesTable)
  299. {
  300. DataMember existingMemberContract;
  301. if (memberNamesTable.TryGetValue(memberContract.Name, out existingMemberContract))
  302. {
  303. Type declaringType = memberContract.MemberInfo.DeclaringType;
  304. DataContract.ThrowInvalidDataContractException(
  305. SR.GetString((declaringType.IsEnum ? SR.DupEnumMemberValue : SR.DupMemberName),
  306. existingMemberContract.MemberInfo.Name,
  307. memberContract.MemberInfo.Name,
  308. DataContract.GetClrTypeFullName(declaringType),
  309. memberContract.Name),
  310. declaringType);
  311. }
  312. memberNamesTable.Add(memberContract.Name, memberContract);
  313. members.Add(memberContract);
  314. }
  315. internal static XmlDictionaryString GetChildNamespaceToDeclare(DataContract dataContract, Type childType, XmlDictionary dictionary)
  316. {
  317. childType = DataContract.UnwrapNullableType(childType);
  318. if (!childType.IsEnum && !Globals.TypeOfIXmlSerializable.IsAssignableFrom(childType)
  319. && DataContract.GetBuiltInDataContract(childType) == null && childType != Globals.TypeOfDBNull)
  320. {
  321. string ns = DataContract.GetStableName(childType).Namespace;
  322. if (ns.Length > 0 && ns != dataContract.Namespace.Value)
  323. return dictionary.Add(ns);
  324. }
  325. return null;
  326. }
  327. [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - callers may need to depend on isNonAttributedType for a security decision."
  328. + "isNonAttributedType must be calculated correctly."
  329. + "IsNonAttributedTypeValidForSerialization is used as part of the isNonAttributedType calculation and is therefore marked with SecurityNote.",
  330. Safe = "Does not let caller influence isNonAttributedType calculation; no harm in leaking value.")]
  331. // check whether a corresponding update is required in DataContractCriticalHelper.CreateDataContract
  332. static internal bool IsNonAttributedTypeValidForSerialization(Type type)
  333. {
  334. if (type.IsArray)
  335. return false;
  336. if (type.IsEnum)
  337. return false;
  338. if (type.IsGenericParameter)
  339. return false;
  340. if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
  341. return false;
  342. if (type.IsPointer)
  343. return false;
  344. if (type.IsDefined(Globals.TypeOfCollectionDataContractAttribute, false))
  345. return false;
  346. Type[] interfaceTypes = type.GetInterfaces();
  347. foreach (Type interfaceType in interfaceTypes)
  348. {
  349. if (CollectionDataContract.IsCollectionInterface(interfaceType))
  350. return false;
  351. }
  352. if (type.IsSerializable)
  353. return false;
  354. if (Globals.TypeOfISerializable.IsAssignableFrom(type))
  355. return false;
  356. if (type.IsDefined(Globals.TypeOfDataContractAttribute, false))
  357. return false;
  358. if (type == Globals.TypeOfExtensionDataObject)
  359. return false;
  360. if (type.IsValueType)
  361. {
  362. return type.IsVisible;
  363. }
  364. else
  365. {
  366. return (type.IsVisible &&
  367. type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Globals.EmptyTypeArray, null) != null);
  368. }
  369. }
  370. XmlDictionaryString[] CreateChildElementNamespaces()
  371. {
  372. if (Members == null)
  373. return null;
  374. XmlDictionaryString[] baseChildElementNamespaces = null;
  375. if (this.BaseContract != null)
  376. baseChildElementNamespaces = this.BaseContract.ChildElementNamespaces;
  377. int baseChildElementNamespaceCount = (baseChildElementNamespaces != null) ? baseChildElementNamespaces.Length : 0;
  378. XmlDictionaryString[] childElementNamespaces = new XmlDictionaryString[Members.Count + baseChildElementNamespaceCount];
  379. if (baseChildElementNamespaceCount > 0)
  380. Array.Copy(baseChildElementNamespaces, 0, childElementNamespaces, 0, baseChildElementNamespaces.Length);
  381. XmlDictionary dictionary = new XmlDictionary();
  382. for (int i = 0; i < this.Members.Count; i++)
  383. {
  384. childElementNamespaces[i + baseChildElementNamespaceCount] = GetChildNamespaceToDeclare(this, this.Members[i].MemberType, dictionary);
  385. }
  386. return childElementNamespaces;
  387. }
  388. [Fx.Tag.SecurityNote(Critical = "Calls critical method on helper.",
  389. Safe = "Doesn't leak anything.")]
  390. [SecuritySafeCritical]
  391. void EnsureMethodsImported()
  392. {
  393. helper.EnsureMethodsImported();
  394. }
  395. public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
  396. {
  397. XmlFormatWriterDelegate(xmlWriter, obj, context, this);
  398. }
  399. public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
  400. {
  401. xmlReader.Read();
  402. object o = XmlFormatReaderDelegate(xmlReader, context, MemberNames, MemberNamespaces);
  403. xmlReader.ReadEndElement();
  404. return o;
  405. }
  406. #if !NO_DYNAMIC_CODEGEN
  407. [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - calculates whether this class requires MemberAccessPermission for deserialization."
  408. + "Since this information is used to determine whether to give the generated code access "
  409. + "permissions to private members, any changes to the logic should be reviewed.")]
  410. internal bool RequiresMemberAccessForRead(SecurityException securityException)
  411. {
  412. EnsureMethodsImported();
  413. if (!IsTypeVisible(UnderlyingType))
  414. {
  415. if (securityException != null)
  416. {
  417. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  418. new SecurityException(SR.GetString(
  419. SR.PartialTrustDataContractTypeNotPublic,
  420. DataContract.GetClrTypeFullName(UnderlyingType)),
  421. securityException));
  422. }
  423. return true;
  424. }
  425. if (this.BaseContract != null && this.BaseContract.RequiresMemberAccessForRead(securityException))
  426. return true;
  427. if (ConstructorRequiresMemberAccess(GetISerializableConstructor()))
  428. {
  429. if (securityException != null)
  430. {
  431. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  432. new SecurityException(SR.GetString(
  433. SR.PartialTrustISerializableNoPublicConstructor,
  434. DataContract.GetClrTypeFullName(UnderlyingType)),
  435. securityException));
  436. }
  437. return true;
  438. }
  439. if (ConstructorRequiresMemberAccess(GetNonAttributedTypeConstructor()))
  440. {
  441. if (securityException != null)
  442. {
  443. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  444. new SecurityException(SR.GetString(
  445. SR.PartialTrustNonAttributedSerializableTypeNoPublicConstructor,
  446. DataContract.GetClrTypeFullName(UnderlyingType)),
  447. securityException));
  448. }
  449. return true;
  450. }
  451. if (MethodRequiresMemberAccess(this.OnDeserializing))
  452. {
  453. if (securityException != null)
  454. {
  455. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  456. new SecurityException(SR.GetString(
  457. SR.PartialTrustDataContractOnDeserializingNotPublic,
  458. DataContract.GetClrTypeFullName(UnderlyingType),
  459. this.OnDeserializing.Name),
  460. securityException));
  461. }
  462. return true;
  463. }
  464. if (MethodRequiresMemberAccess(this.OnDeserialized))
  465. {
  466. if (securityException != null)
  467. {
  468. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  469. new SecurityException(SR.GetString(
  470. SR.PartialTrustDataContractOnDeserializedNotPublic,
  471. DataContract.GetClrTypeFullName(UnderlyingType),
  472. this.OnDeserialized.Name),
  473. securityException));
  474. }
  475. return true;
  476. }
  477. if (this.Members != null)
  478. {
  479. for (int i = 0; i < this.Members.Count; i++)
  480. {
  481. if (this.Members[i].RequiresMemberAccessForSet())
  482. {
  483. if (securityException != null)
  484. {
  485. if (this.Members[i].MemberInfo is FieldInfo)
  486. {
  487. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  488. new SecurityException(SR.GetString(
  489. SR.PartialTrustDataContractFieldSetNotPublic,
  490. DataContract.GetClrTypeFullName(UnderlyingType),
  491. this.Members[i].MemberInfo.Name),
  492. securityException));
  493. }
  494. else
  495. {
  496. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  497. new SecurityException(SR.GetString(
  498. SR.PartialTrustDataContractPropertySetNotPublic,
  499. DataContract.GetClrTypeFullName(UnderlyingType),
  500. this.Members[i].MemberInfo.Name),
  501. securityException));
  502. }
  503. }
  504. return true;
  505. }
  506. }
  507. }
  508. return false;
  509. }
  510. [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - calculates whether this class requires MemberAccessPermission for serialization."
  511. + " Since this information is used to determine whether to give the generated code access"
  512. + " permissions to private members, any changes to the logic should be reviewed.")]
  513. internal bool RequiresMemberAccessForWrite(SecurityException securityException)
  514. {
  515. #if FEATURE_MONO_CAS
  516. EnsureMethodsImported();
  517. if (!IsTypeVisible(UnderlyingType))
  518. {
  519. if (securityException != null)
  520. {
  521. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  522. new SecurityException(SR.GetString(
  523. SR.PartialTrustDataContractTypeNotPublic,
  524. DataContract.GetClrTypeFullName(UnderlyingType)),
  525. securityException));
  526. }
  527. return true;
  528. }
  529. if (this.BaseContract != null && this.BaseContract.RequiresMemberAccessForWrite(securityException))
  530. return true;
  531. if (MethodRequiresMemberAccess(this.OnSerializing))
  532. {
  533. if (securityException != null)
  534. {
  535. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  536. new SecurityException(SR.GetString(
  537. SR.PartialTrustDataContractOnSerializingNotPublic,
  538. DataContract.GetClrTypeFullName(this.UnderlyingType),
  539. this.OnSerializing.Name),
  540. securityException));
  541. }
  542. return true;
  543. }
  544. if (MethodRequiresMemberAccess(this.OnSerialized))
  545. {
  546. if (securityException != null)
  547. {
  548. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  549. new SecurityException(SR.GetString(
  550. SR.PartialTrustDataContractOnSerializedNotPublic,
  551. DataContract.GetClrTypeFullName(UnderlyingType),
  552. this.OnSerialized.Name),
  553. securityException));
  554. }
  555. return true;
  556. }
  557. if (this.Members != null)
  558. {
  559. for (int i = 0; i < this.Members.Count; i++)
  560. {
  561. if (this.Members[i].RequiresMemberAccessForGet())
  562. {
  563. if (securityException != null)
  564. {
  565. if (this.Members[i].MemberInfo is FieldInfo)
  566. {
  567. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  568. new SecurityException(SR.GetString(
  569. SR.PartialTrustDataContractFieldGetNotPublic,
  570. DataContract.GetClrTypeFullName(UnderlyingType),
  571. this.Members[i].MemberInfo.Name),
  572. securityException));
  573. }
  574. else
  575. {
  576. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  577. new SecurityException(SR.GetString(
  578. SR.PartialTrustDataContractPropertyGetNotPublic,
  579. DataContract.GetClrTypeFullName(UnderlyingType),
  580. this.Members[i].MemberInfo.Name),
  581. securityException));
  582. }
  583. }
  584. return true;
  585. }
  586. }
  587. }
  588. return false;
  589. #else
  590. return true;
  591. #endif
  592. }
  593. #endif
  594. [Fx.Tag.SecurityNote(Critical = "Holds all state used for (de)serializing classes."
  595. + " Since the data is cached statically, we lock down access to it.")]
  596. #if !NO_SECURITY_ATTRIBUTES
  597. [SecurityCritical(SecurityCriticalScope.Everything)]
  598. #endif
  599. class ClassDataContractCriticalHelper : DataContract.DataContractCriticalHelper
  600. {
  601. ClassDataContract baseContract;
  602. List<DataMember> members;
  603. MethodInfo onSerializing, onSerialized;
  604. MethodInfo onDeserializing, onDeserialized;
  605. MethodInfo extensionDataSetMethod;
  606. DataContractDictionary knownDataContracts;
  607. string serializationExceptionMessage;
  608. bool isISerializable;
  609. bool isKnownTypeAttributeChecked;
  610. bool isMethodChecked;
  611. bool hasExtensionData;
  612. [Fx.Tag.SecurityNote(Miscellaneous = "in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and hasDataContract.")]
  613. bool isNonAttributedType;
  614. [Fx.Tag.SecurityNote(Miscellaneous = "in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and isNonAttributedType.")]
  615. bool hasDataContract;
  616. XmlDictionaryString[] childElementNamespaces;
  617. XmlFormatClassReaderDelegate xmlFormatReaderDelegate;
  618. XmlFormatClassWriterDelegate xmlFormatWriterDelegate;
  619. public XmlDictionaryString[] ContractNamespaces;
  620. public XmlDictionaryString[] MemberNames;
  621. public XmlDictionaryString[] MemberNamespaces;
  622. internal ClassDataContractCriticalHelper()
  623. : base()
  624. {
  625. }
  626. internal ClassDataContractCriticalHelper(Type type)
  627. : base(type)
  628. {
  629. XmlQualifiedName stableName = GetStableNameAndSetHasDataContract(type);
  630. if (type == Globals.TypeOfDBNull)
  631. {
  632. this.StableName = stableName;
  633. this.members = new List<DataMember>();
  634. XmlDictionary dictionary = new XmlDictionary(2);
  635. this.Name = dictionary.Add(StableName.Name);
  636. this.Namespace = dictionary.Add(StableName.Namespace);
  637. this.ContractNamespaces = this.MemberNames = this.MemberNamespaces = new XmlDictionaryString[] { };
  638. EnsureMethodsImported();
  639. return;
  640. }
  641. Type baseType = type.BaseType;
  642. this.isISerializable = (Globals.TypeOfISerializable.IsAssignableFrom(type));
  643. SetIsNonAttributedType(type);
  644. if (this.isISerializable)
  645. {
  646. if (HasDataContract)
  647. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.ISerializableCannotHaveDataContract, DataContract.GetClrTypeFullName(type))));
  648. if (baseType != null && !(baseType.IsSerializable && Globals.TypeOfISerializable.IsAssignableFrom(baseType)))
  649. baseType = null;
  650. }
  651. this.IsValueType = type.IsValueType;
  652. if (baseType != null && baseType != Globals.TypeOfObject && baseType != Globals.TypeOfValueType && baseType != Globals.TypeOfUri)
  653. {
  654. DataContract baseContract = DataContract.GetDataContract(baseType);
  655. if (baseContract is CollectionDataContract)
  656. this.BaseContract = ((CollectionDataContract)baseContract).SharedTypeContract as ClassDataContract;
  657. else
  658. this.BaseContract = baseContract as ClassDataContract;
  659. if (this.BaseContract != null && this.BaseContract.IsNonAttributedType && !this.isNonAttributedType)
  660. {
  661. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError
  662. (new InvalidDataContractException(SR.GetString(SR.AttributedTypesCannotInheritFromNonAttributedSerializableTypes,
  663. DataContract.GetClrTypeFullName(type), DataContract.GetClrTypeFullName(baseType))));
  664. }
  665. }
  666. else
  667. this.BaseContract = null;
  668. hasExtensionData = (Globals.TypeOfIExtensibleDataObject.IsAssignableFrom(type));
  669. if (hasExtensionData && !HasDataContract && !IsNonAttributedType)
  670. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.OnlyDataContractTypesCanHaveExtensionData, DataContract.GetClrTypeFullName(type))));
  671. if (this.isISerializable)
  672. SetDataContractName(stableName);
  673. else
  674. {
  675. this.StableName = stableName;
  676. ImportDataMembers();
  677. XmlDictionary dictionary = new XmlDictionary(2 + Members.Count);
  678. Name = dictionary.Add(StableName.Name);
  679. Namespace = dictionary.Add(StableName.Namespace);
  680. int baseMemberCount = 0;
  681. int baseContractCount = 0;
  682. if (BaseContract == null)
  683. {
  684. MemberNames = new XmlDictionaryString[Members.Count];
  685. MemberNamespaces = new XmlDictionaryString[Members.Count];
  686. ContractNamespaces = new XmlDictionaryString[1];
  687. }
  688. else
  689. {
  690. if (BaseContract.IsReadOnlyContract)
  691. {
  692. this.serializationExceptionMessage = BaseContract.SerializationExceptionMessage;
  693. }
  694. baseMemberCount = BaseContract.MemberNames.Length;
  695. MemberNames = new XmlDictionaryString[Members.Count + baseMemberCount];
  696. Array.Copy(BaseContract.MemberNames, MemberNames, baseMemberCount);
  697. MemberNamespaces = new XmlDictionaryString[Members.Count + baseMemberCount];
  698. Array.Copy(BaseContract.MemberNamespaces, MemberNamespaces, baseMemberCount);
  699. baseContractCount = BaseContract.ContractNamespaces.Length;
  700. ContractNamespaces = new XmlDictionaryString[1 + baseContractCount];
  701. Array.Copy(BaseContract.ContractNamespaces, ContractNamespaces, baseContractCount);
  702. }
  703. ContractNamespaces[baseContractCount] = Namespace;
  704. for (int i = 0; i < Members.Count; i++)
  705. {
  706. MemberNames[i + baseMemberCount] = dictionary.Add(Members[i].Name);
  707. MemberNamespaces[i + baseMemberCount] = Namespace;
  708. }
  709. }
  710. EnsureMethodsImported();
  711. }
  712. internal ClassDataContractCriticalHelper(Type type, XmlDictionaryString ns, string[] memberNames)
  713. : base(type)
  714. {
  715. this.StableName = new XmlQualifiedName(GetStableNameAndSetHasDataContract(type).Name, ns.Value);
  716. ImportDataMembers();
  717. XmlDictionary dictionary = new XmlDictionary(1 + Members.Count);
  718. Name = dictionary.Add(StableName.Name);
  719. Namespace = ns;
  720. ContractNamespaces = new XmlDictionaryString[] { Namespace };
  721. MemberNames = new XmlDictionaryString[Members.Count];
  722. MemberNamespaces = new XmlDictionaryString[Members.Count];
  723. for (int i = 0; i < Members.Count; i++)
  724. {
  725. Members[i].Name = memberNames[i];
  726. MemberNames[i] = dictionary.Add(Members[i].Name);
  727. MemberNamespaces[i] = Namespace;
  728. }
  729. EnsureMethodsImported();
  730. }
  731. void EnsureIsReferenceImported(Type type)
  732. {
  733. DataContractAttribute dataContractAttribute;
  734. bool isReference = false;
  735. bool hasDataContractAttribute = TryGetDCAttribute(type, out dataContractAttribute);
  736. if (BaseContract != null)
  737. {
  738. if (hasDataContractAttribute && dataContractAttribute.IsReferenceSetExplicitly)
  739. {
  740. bool baseIsReference = this.BaseContract.IsReference;
  741. if ((baseIsReference && !dataContractAttribute.IsReference) ||
  742. (!baseIsReference && dataContractAttribute.IsReference))
  743. {
  744. DataContract.ThrowInvalidDataContractException(
  745. SR.GetString(SR.InconsistentIsReference,
  746. DataContract.GetClrTypeFullName(type),
  747. dataContractAttribute.IsReference,
  748. DataContract.GetClrTypeFullName(this.BaseContract.UnderlyingType),
  749. this.BaseContract.IsReference),
  750. type);
  751. }
  752. else
  753. {
  754. isReference = dataContractAttribute.IsReference;
  755. }
  756. }
  757. else
  758. {
  759. isReference = this.BaseContract.IsReference;
  760. }
  761. }
  762. else if (hasDataContractAttribute)
  763. {
  764. if (dataContractAttribute.IsReference)
  765. isReference = dataContractAttribute.IsReference;
  766. }
  767. if (isReference && type.IsValueType)
  768. {
  769. DataContract.ThrowInvalidDataContractException(
  770. SR.GetString(SR.ValueTypeCannotHaveIsReference,
  771. DataContract.GetClrTypeFullName(type),
  772. true,
  773. false),
  774. type);
  775. return;
  776. }
  777. this.IsReference = isReference;
  778. }
  779. void ImportDataMembers()
  780. {
  781. Type type = this.UnderlyingType;
  782. EnsureIsReferenceImported(type);
  783. List<DataMember> tempMembers = new List<DataMember>();
  784. Dictionary<string, DataMember> memberNamesTable = new Dictionary<string, DataMember>();
  785. MemberInfo[] memberInfos;
  786. if (this.isNonAttributedType)
  787. {
  788. memberInfos = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
  789. }
  790. else
  791. {
  792. memberInfos = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  793. }
  794. for (int i = 0; i < memberInfos.Length; i++)
  795. {
  796. MemberInfo member = memberInfos[i];
  797. if (HasDataContract)
  798. {
  799. object[] memberAttributes = member.GetCustomAttributes(typeof(DataMemberAttribute), false);
  800. if (memberAttributes != null && memberAttributes.Length > 0)
  801. {
  802. if (memberAttributes.Length > 1)
  803. ThrowInvalidDataContractException(SR.GetString(SR.TooManyDataMembers, DataContract.GetClrTypeFullName(member.DeclaringType), member.Name));
  804. DataMember memberContract = new DataMember(member);
  805. if (member.MemberType == MemberTypes.Property)
  806. {
  807. PropertyInfo property = (PropertyInfo)member;
  808. MethodInfo getMethod = property.GetGetMethod(true);
  809. if (getMethod != null && IsMethodOverriding(getMethod))
  810. continue;
  811. MethodInfo setMethod = property.GetSetMethod(true);
  812. if (setMethod != null && IsMethodOverriding(setMethod))
  813. continue;
  814. if (getMethod == null)
  815. ThrowInvalidDataContractException(SR.GetString(SR.NoGetMethodForProperty, property.DeclaringType, property.Name));
  816. if (setMethod == null)
  817. {
  818. if (!SetIfGetOnlyCollection(memberContract, skipIfReadOnlyContract: false))
  819. {
  820. this.serializationExceptionMessage = SR.GetString(SR.NoSetMethodForProperty, property.DeclaringType, property.Name);
  821. }
  822. }
  823. if (getMethod.GetParameters().Length > 0)
  824. ThrowInvalidDataContractException(SR.GetString(SR.IndexedPropertyCannotBeSerialized, property.DeclaringType, property.Name));
  825. }
  826. else if (member.MemberType != MemberTypes.Field)
  827. ThrowInvalidDataContractException(SR.GetString(SR.InvalidMember, DataContract.GetClrTypeFullName(type), member.Name));
  828. DataMemberAttribute memberAttribute = (DataMemberAttribute)memberAttributes[0];
  829. if (memberAttribute.IsNameSetExplicitly)
  830. {
  831. if (memberAttribute.Name == null || memberAttribute.Name.Length == 0)
  832. ThrowInvalidDataContractException(SR.GetString(SR.InvalidDataMemberName, member.Name, DataContract.GetClrTypeFullName(type)));
  833. memberContract.Name = memberAttribute.Name;
  834. }
  835. else
  836. memberContract.Name = member.Name;
  837. memberContract.Name = DataContract.EncodeLocalName(memberContract.Name);
  838. memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType);
  839. memberContract.IsRequired = memberAttribute.IsRequired;
  840. if (memberAttribute.IsRequired && this.IsReference)
  841. {
  842. ThrowInvalidDataContractException(
  843. SR.GetString(SR.IsRequiredDataMemberOnIsReferenceDataContractType,
  844. DataContract.GetClrTypeFullName(member.DeclaringType),
  845. member.Name, true), type);
  846. }
  847. memberContract.EmitDefaultValue = memberAttribute.EmitDefaultValue;
  848. memberContract.Order = memberAttribute.Order;
  849. CheckAndAddMember(tempMembers, memberContract, memberNamesTable);
  850. }
  851. }
  852. else if (this.isNonAttributedType)
  853. {
  854. FieldInfo field = member as FieldInfo;
  855. PropertyInfo property = member as PropertyInfo;
  856. if ((field == null && property == null) || (field != null && field.IsInitOnly))
  857. continue;
  858. object[] memberAttributes = member.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), false);
  859. if (memberAttributes != null && memberAttributes.Length > 0)
  860. {
  861. if (memberAttributes.Length > 1)
  862. ThrowInvalidDataContractException(SR.GetString(SR.TooManyIgnoreDataMemberAttributes, DataContract.GetClrTypeFullName(member.DeclaringType), member.Name));
  863. else
  864. continue;
  865. }
  866. DataMember memberContract = new DataMember(member);
  867. if (property != null)
  868. {
  869. MethodInfo getMethod = property.GetGetMethod();
  870. if (getMethod == null || IsMethodOverriding(getMethod) || getMethod.GetParameters().Length > 0)
  871. continue;
  872. MethodInfo setMethod = property.GetSetMethod(true);
  873. if (setMethod == null)
  874. {
  875. // if the collection doesn't have the 'Add' method, we will skip it, for compatibility with 4.0
  876. if (!SetIfGetOnlyCollection(memberContract, skipIfReadOnlyContract: true))
  877. continue;
  878. }
  879. else
  880. {
  881. if (!setMethod.IsPublic || IsMethodOverriding(setMethod))
  882. continue;
  883. }
  884. //skip ExtensionData member of type ExtensionDataObject if IExtensibleDataObject is implemented in non-attributed type
  885. if (this.hasExtensionData && memberContract.MemberType == Globals.TypeOfExtensionDataObject
  886. && member.Name == Globals.ExtensionDataObjectPropertyName)
  887. continue;
  888. }
  889. memberContract.Name = DataContract.EncodeLocalName(member.Name);
  890. memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType);
  891. CheckAndAddMember(tempMembers, memberContract, memberNamesTable);
  892. }
  893. else
  894. {
  895. FieldInfo field = member as FieldInfo;
  896. if (field != null && !field.IsNotSerialized)
  897. {
  898. DataMember memberContract = new DataMember(member);
  899. memberContract.Name = DataContract.EncodeLocalName(member.Name);
  900. object[] optionalFields = field.GetCustomAttributes(Globals.TypeOfOptionalFieldAttribute, false);
  901. if (optionalFields == null || optionalFields.Length == 0)
  902. {
  903. if (this.IsReference)
  904. {
  905. ThrowInvalidDataContractException(
  906. SR.GetString(SR.NonOptionalFieldMemberOnIsReferenceSerializableType,
  907. DataContract.GetClrTypeFullName(member.DeclaringType),
  908. member.Name, true), type);
  909. }
  910. memberContract.IsRequired = true;
  911. }
  912. memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType);
  913. CheckAndAddMember(tempMembers, memberContract, memberNamesTable);
  914. }
  915. }
  916. }
  917. if (tempMembers.Count > 1)
  918. tempMembers.Sort(DataMemberComparer.Singleton);
  919. SetIfMembersHaveConflict(tempMembers);
  920. Thread.MemoryBarrier();
  921. members = tempMembers;
  922. }
  923. bool SetIfGetOnlyCollection(DataMember memberContract, bool skipIfReadOnlyContract)
  924. {
  925. //OK to call IsCollection here since the use of surrogated collection types is not supported in get-only scenarios
  926. if (CollectionDataContract.IsCollection(memberContract.MemberType, false /*isConstructorRequired*/, skipIfReadOnlyContract) && !memberContract.MemberType.IsValueType)
  927. {
  928. memberContract.IsGetOnlyCollection = true;
  929. return true;
  930. }
  931. return false;
  932. }
  933. void SetIfMembersHaveConflict(List<DataMember> members)
  934. {
  935. if (BaseContract == null)
  936. return;
  937. int baseTypeIndex = 0;
  938. List<Member> membersInHierarchy = new List<Member>();
  939. foreach (DataMember member in members)
  940. {
  941. membersInHierarchy.Add(new Member(member, this.StableName.Namespace, baseTypeIndex));
  942. }
  943. ClassDataContract currContract = BaseContract;
  944. while (currContract != null)
  945. {
  946. baseTypeIndex++;
  947. foreach (DataMember member in currContract.Members)
  948. {
  949. membersInHierarchy.Add(new Member(member, currContract.StableName.Namespace, baseTypeIndex));
  950. }
  951. currContract = currContract.BaseContract;
  952. }
  953. IComparer<Member> comparer = DataMemberConflictComparer.Singleton;
  954. membersInHierarchy.Sort(comparer);
  955. for (int i = 0; i < membersInHierarchy.Count - 1; i++)
  956. {
  957. int startIndex = i;
  958. int endIndex = i;
  959. bool hasConflictingType = false;
  960. while (endIndex < membersInHierarchy.Count - 1
  961. && String.CompareOrdinal(membersInHierarchy[endIndex].member.Name, membersInHierarchy[endIndex + 1].member.Name) == 0
  962. && String.CompareOrdinal(membersInHierarchy[endIndex].ns, membersInHierarchy[endIndex + 1].ns) == 0)
  963. {
  964. membersInHierarchy[endIndex].member.ConflictingMember = membersInHierarchy[endIndex + 1].member;
  965. if (!hasConflictingType)
  966. {
  967. if (membersInHierarchy[endIndex + 1].member.HasConflictingNameAndType)
  968. {
  969. hasConflictingType = true;
  970. }
  971. else
  972. {
  973. hasConflictingType = (membersInHierarchy[endIndex].member.MemberType != membersInHierarchy[endIndex + 1].member.MemberType);
  974. }
  975. }
  976. endIndex++;
  977. }
  978. if (hasConflictingType)
  979. {
  980. for (int j = startIndex; j <= endIndex; j++)
  981. {
  982. membersInHierarchy[j].member.HasConflictingNameAndType = true;
  983. }
  984. }
  985. i = endIndex + 1;
  986. }
  987. }
  988. [Fx.Tag.SecurityNote(Critical = "Sets the critical hasDataContract field.",
  989. Safe = "Uses a trusted critical API (DataContract.GetStableName) to calculate the value, does not accept the value from the caller.")]
  990. [SecuritySafeCritical]
  991. XmlQualifiedName GetStableNameAndSetHasDataContract(Type type)
  992. {
  993. return DataContract.GetStableName(type, out this.hasDataContract);
  994. }
  995. [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - callers may need to depend on isNonAttributedType for a security decision."
  996. + "isNonAttributedType must be calculated correctly."
  997. + "SetIsNonAttributedType should not be called before GetStableNameAndSetHasDataContract since it is dependent on the correct calculation of hasDataContract.",
  998. Safe = "Does not let caller influence isNonAttributedType calculation; no harm in leaking value.")]
  999. void SetIsNonAttributedType(Type type)
  1000. {
  1001. this.isNonAttributedType = !type.IsSerializable && !this.hasDataContract && IsNonAttributedTypeValidForSerialization(type);
  1002. }
  1003. static bool IsMethodOverriding(MethodInfo method)
  1004. {
  1005. return method.IsVirtual && ((method.Attributes & MethodAttributes.NewSlot) == 0);
  1006. }
  1007. internal void EnsureMethodsImported()
  1008. {
  1009. if (!isMethodChecked && UnderlyingType != null)
  1010. {
  1011. lock (this)
  1012. {
  1013. if (!isMethodChecked)
  1014. {
  1015. Type type = this.UnderlyingType;
  1016. MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  1017. for (int i = 0; i < methods.Length; i++)
  1018. {
  1019. MethodInfo method = methods[i];
  1020. Type prevAttributeType = null;
  1021. ParameterInfo[] parameters = method.GetParameters();
  1022. if (HasExtensionData && IsValidExtensionDataSetMethod(method, parameters))
  1023. {
  1024. if (method.Name == Globals.ExtensionDataSetExplicitMethod || !method.IsPublic)
  1025. extensionDataSetMethod = XmlFormatGeneratorStatics.ExtensionDataSetExplicitMethodInfo;
  1026. else
  1027. extensionDataSetMethod = method;
  1028. }
  1029. if (IsValidCallback(method, parameters, Globals.TypeOfOnSerializingAttribute, onSerializing, ref prevAttributeType))
  1030. onSerializing = method;
  1031. if (IsValidCallback(method, parameters, Globals.TypeOfOnSerializedAttribute, onSerialized, ref prevAttributeType))
  1032. onSerialized = method;
  1033. if (IsValidCallback(method, parameters, Globals.TypeOfOnDeserializingAttribute, onDeserializing, ref prevAttributeType))
  1034. onDeserializing = method;
  1035. if (IsValidCallback(method, parameters, Globals.TypeOfOnDeserializedAttribute, onDeserialized, ref prevAttributeType))
  1036. onDeserialized = method;
  1037. }
  1038. Thread.MemoryBarrier();
  1039. isMethodChecked = true;
  1040. }
  1041. }
  1042. }
  1043. }
  1044. bool IsValidExtensionDataSetMethod(MethodInfo method, ParameterInfo[] parameters)
  1045. {
  1046. if (method.Name == Globals.ExtensionDataSetExplicitMethod || method.Name == Globals.ExtensionDataSetMethod)
  1047. {
  1048. if (extensionDataSetMethod != null)
  1049. ThrowInvalidDataContractException(SR.GetString(SR.DuplicateExtensionDataSetMethod, method, extensionDataSetMethod, DataContract.GetClrTypeFullName(method.DeclaringType)));
  1050. if (method.ReturnType != Globals.TypeOfVoid)
  1051. DataContract.ThrowInvalidDataContractException(SR.GetString(SR.ExtensionDataSetMustReturnVoid, DataContract.GetClrTypeFullName(method.DeclaringType), method), method.DeclaringType);
  1052. if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != Globals.TypeOfExtensionDataObject)
  1053. DataContract.ThrowInvalidDataContractException(SR.GetString(SR.ExtensionDataSetParameterInvalid, DataContract.GetClrTypeFullName(method.DeclaringType), method, Globals.TypeOfExtensionDataObject), method.DeclaringType);
  1054. return true;
  1055. }
  1056. return false;
  1057. }
  1058. static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo currentCallback, ref Type prevAttributeType)
  1059. {
  1060. if (method.IsDefined(attributeType, false))
  1061. {
  1062. if (currentCallback != null)
  1063. DataContract.ThrowInvalidDataContractException(SR.GetString(SR.DuplicateCallback, method, currentCallback, DataContract.GetClrTypeFullName(method.DeclaringType), attributeType), method.DeclaringType);
  1064. else if (prevAttributeType != null)
  1065. DataContract.ThrowInvalidDataContractException(SR.GetString(SR.DuplicateAttribute, prevAttributeType, attributeType, DataContract.GetClrTypeFullName(method.DeclaringType), method), method.DeclaringType);
  1066. else if (method.IsVirtual)
  1067. DataContract.ThrowInvalidDataContractException(SR.GetString(SR.CallbacksCannotBeVirtualMethods, method, DataContract.GetClrTypeFullName(method.DeclaringType), attributeType), method.DeclaringType);
  1068. else
  1069. {
  1070. if (method.ReturnType != Globals.TypeOfVoid)
  1071. DataContract.ThrowInvalidDataContractException(SR.GetString(SR.CallbackMustReturnVoid, DataContract.GetClrTypeFullName(method.DeclaringType), method), method.DeclaringType);
  1072. if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != Globals.TypeOfStreamingContext)
  1073. DataContract.ThrowInvalidDataContractException(SR.GetString(SR.CallbackParameterInvalid, DataContract.GetClrTypeFullName(method.DeclaringType), method, Globals.TypeOfStreamingContext), method.DeclaringType);
  1074. prevAttributeType = attributeType;
  1075. }
  1076. return true;
  1077. }
  1078. return false;
  1079. }
  1080. internal ClassDataContract BaseContract
  1081. {
  1082. get { return baseContract; }
  1083. set
  1084. {
  1085. baseContract = value;
  1086. if (baseContract != null && IsValueType)
  1087. ThrowInvalidDataContractException(SR.GetString(SR.ValueTypeCannotHaveBaseType, StableName.Name, StableName.Namespace, baseContract.StableName.Name, baseContract.StableName.Namespace));
  1088. }
  1089. }
  1090. internal List<DataMember> Members
  1091. {
  1092. get { return members; }
  1093. set { members = value; }
  1094. }
  1095. internal MethodInfo OnSerializing
  1096. {
  1097. get
  1098. {
  1099. EnsureMethodsImported();
  1100. return onSerializing;
  1101. }
  1102. }
  1103. internal MethodInfo OnSerialized
  1104. {
  1105. get
  1106. {
  1107. EnsureMethodsImported();
  1108. return onSerialized;
  1109. }
  1110. }
  1111. internal MethodInfo OnDeserializing
  1112. {
  1113. get
  1114. {
  1115. EnsureMethodsImported();
  1116. return onDeserializing;
  1117. }
  1118. }
  1119. internal MethodInfo OnDeserialized
  1120. {
  1121. get
  1122. {
  1123. EnsureMethodsImported();
  1124. return onDeserialized;
  1125. }
  1126. }
  1127. internal MethodInfo ExtensionDataSetMethod
  1128. {
  1129. get
  1130. {
  1131. EnsureMethodsImported();
  1132. return extensionDataSetMethod;
  1133. }
  1134. }
  1135. internal override DataContractDictionary KnownDataContracts
  1136. {
  1137. get
  1138. {
  1139. if (!isKnownTypeAttributeChecked && UnderlyingType != null)
  1140. {
  1141. lock (this)
  1142. {
  1143. if (!isKnownTypeAttributeChecked)
  1144. {
  1145. knownDataContracts = DataContract.ImportKnownTypeAttributes(this.UnderlyingType);
  1146. Thread.MemoryBarrier();
  1147. isKnownTypeAttributeChecked = true;
  1148. }
  1149. }
  1150. }
  1151. return knownDataContracts;
  1152. }
  1153. set { knownDataContracts = value; }
  1154. }
  1155. internal string SerializationExceptionMessage
  1156. {
  1157. get { return serializationExceptionMessage; }
  1158. }
  1159. internal string DeserializationExceptionMessage
  1160. {
  1161. get
  1162. {
  1163. if (serializationExceptionMessage == null)
  1164. {
  1165. return null;
  1166. }
  1167. else
  1168. {
  1169. return SR.GetString(SR.ReadOnlyClassDeserialization, this.serializationExceptionMessage);
  1170. }
  1171. }
  1172. }
  1173. internal override bool IsISerializable
  1174. {
  1175. get { return isISerializable; }
  1176. set { isISerializable = value; }
  1177. }
  1178. internal bool HasDataContract
  1179. {
  1180. get { return hasDataContract; }
  1181. }
  1182. internal bool HasExtensionData
  1183. {
  1184. get { return hasExtensionData; }
  1185. }
  1186. internal bool IsNonAttributedType
  1187. {
  1188. get { return isNonAttributedType; }
  1189. }
  1190. internal ConstructorInfo GetISerializableConstructor()
  1191. {
  1192. if (!IsISerializable)
  1193. return null;
  1194. ConstructorInfo ctor = UnderlyingType.GetConstructor(Globals.ScanAllMembers, null, SerInfoCtorArgs, null);
  1195. if (ctor == null)
  1196. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.SerializationInfo_ConstructorNotFound, DataContract.GetClrTypeFullName(UnderlyingType))));
  1197. return ctor;
  1198. }
  1199. internal ConstructorInfo GetNonAttributedTypeConstructor()
  1200. {
  1201. if (!this.IsNonAttributedType)
  1202. return null;
  1203. Type type = UnderlyingType;
  1204. if (type.IsValueType)
  1205. return null;
  1206. ConstructorInfo ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
  1207. if (ctor == null)
  1208. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.NonAttributedSerializableTypesMustHaveDefaultConstructor, DataContract.GetClrTypeFullName(type))));
  1209. return ctor;
  1210. }
  1211. internal XmlFormatClassWriterDelegate XmlFormatWriterDelegate
  1212. {
  1213. get { return xmlFormatWriterDelegate; }
  1214. set { xmlFormatWriterDelegate = value; }
  1215. }
  1216. internal XmlFormatClassReaderDelegate XmlFormatReaderDelegate
  1217. {
  1218. get { return xmlFormatReaderDelegate; }
  1219. set { xmlFormatReaderDelegate = value; }
  1220. }
  1221. public XmlDictionaryString[] ChildElementNamespaces
  1222. {
  1223. get { return childElementNamespaces; }
  1224. set { childElementNamespaces = value; }
  1225. }
  1226. static Type[] serInfoCtorArgs;
  1227. static Type[] SerInfoCtorArgs
  1228. {
  1229. get
  1230. {
  1231. if (serInfoCtorArgs == null)
  1232. serInfoCtorArgs = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
  1233. return serInfoCtorArgs;
  1234. }
  1235. }
  1236. internal struct Member
  1237. {
  1238. internal Member(DataMember member, string ns, int baseTypeIndex)
  1239. {
  1240. this.member = member;
  1241. this.ns = ns;
  1242. this.baseTypeIndex = baseTypeIndex;
  1243. }
  1244. internal DataMember member;
  1245. internal string ns;
  1246. internal int baseTypeIndex;
  1247. }
  1248. internal class DataMemberConflictComparer : IComparer<Member>
  1249. {
  1250. public int Compare(Member x, Member y)
  1251. {
  1252. int nsCompare = String.CompareOrdinal(x.ns, y.ns);
  1253. if (nsCompare != 0)
  1254. return nsCompare;
  1255. int nameCompare = String.CompareOrdinal(x.member.Name, y.member.Name);
  1256. if (nameCompare != 0)
  1257. return nameCompare;
  1258. return x.baseTypeIndex - y.baseTypeIndex;
  1259. }
  1260. internal static DataMemberConflictComparer Singleton = new DataMemberConflictComparer();
  1261. }
  1262. }
  1263. [Fx.Tag.SecurityNote(Critical = "Sets critical properties on ClassDataContract .",
  1264. Safe = "Called during schema import/code generation.")]
  1265. [SecuritySafeCritical]
  1266. internal override DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary<DataContract, DataContract> boundContracts)
  1267. {
  1268. Type type = UnderlyingType;
  1269. if (!type.IsGenericType || !type.ContainsGenericParameters)
  1270. return this;
  1271. lock (this)
  1272. {
  1273. DataContract boundContract;
  1274. if (boundContracts.TryGetValue(this, out boundContract))
  1275. return boundContract;
  1276. ClassDataContract boundClassContract = new ClassDataContract();
  1277. boundContracts.Add(this, boundClassContract);
  1278. XmlQualifiedName stableName;
  1279. object[] genericParams;
  1280. if (type.IsGenericTypeDefinition)
  1281. {
  1282. stableName = this.StableName;
  1283. genericParams = paramContracts;
  1284. }
  1285. else
  1286. {
  1287. //partial Generic: Construct stable name from its open generic type definition
  1288. stableName = DataContract.GetStableName(type.GetGenericTypeDefinition());
  1289. Type[] paramTypes = type.GetGenericArguments();
  1290. genericParams = new object[paramTypes.Length];
  1291. for (int i = 0; i < paramTypes.Length; i++)
  1292. {
  1293. Type paramType = paramTypes[i];
  1294. if (paramType.IsGenericParameter)
  1295. genericParams[i] = paramContracts[paramType.GenericParameterPosition];
  1296. else
  1297. genericParams[i] = paramType;
  1298. }
  1299. }
  1300. boundClassContract.StableName = CreateQualifiedName(DataContract.ExpandGenericParameters(XmlConvert.DecodeName(stableName.Name), new GenericNameProvider(DataContract.GetClrTypeFullName(this.UnderlyingType), genericParams)), stableName.Namespace);
  1301. if (BaseContract != null)
  1302. boundClassContract.BaseContract = (ClassDataContract)BaseContract.BindGenericParameters(paramContracts, boundContracts);
  1303. boundClassContract.IsISerializable = this.IsISerializable;
  1304. boundClassContract.IsValueType = this.IsValueType;
  1305. boundClassContract.IsReference = this.IsReference;
  1306. if (Members != null)
  1307. {
  1308. boundClassContract.Members = new List<DataMember>(Members.Count);
  1309. foreach (DataMember member in Members)
  1310. boundClassContract.Members.Add(member.BindGenericParameters(paramContracts, boundContracts));
  1311. }
  1312. return boundClassContract;
  1313. }
  1314. }
  1315. internal override bool Equals(object other, Dictionary<DataContractPairKey, object> checkedContracts)
  1316. {
  1317. if (IsEqualOrChecked(other, checkedContracts))
  1318. return true;
  1319. if (base.Equals(other, checkedContracts))
  1320. {
  1321. ClassDataContract dataContract = other as ClassDataContract;
  1322. if (dataContract != null)
  1323. {
  1324. if (IsISerializable)
  1325. {
  1326. if (!dataContract.IsISerializable)
  1327. return false;
  1328. }
  1329. else
  1330. {
  1331. if (dataContract.IsISerializable)
  1332. return false;
  1333. if (Members == null)
  1334. {
  1335. if (dataContract.Members != null)
  1336. {
  1337. // check that all the datamembers in dataContract.Members are optional
  1338. if (!IsEveryDataMemberOptional(dataContract.Members))
  1339. return false;
  1340. }
  1341. }
  1342. else if (dataContract.Members == null)
  1343. {
  1344. // check that all the datamembers in Members are optional
  1345. if (!IsEveryDataMemberOptional(Members))
  1346. return false;
  1347. }
  1348. else
  1349. {
  1350. Dictionary<string, DataMember> membersDictionary = new Dictionary<string, DataMember>(Members.Count);
  1351. List<DataMember> dataContractMembersList = new List<DataMember>();
  1352. for (int i = 0; i < Members.Count; i++)
  1353. {
  1354. membersDictionary.Add(Members[i].Name, Members[i]);
  1355. }
  1356. for (int i = 0; i < dataContract.Members.Count; i++)
  1357. {
  1358. // check that all datamembers common to both datacontracts match
  1359. DataMember dataMember;
  1360. if (membersDictionary.TryGetValue(dataContract.Members[i].Name, out dataMember))
  1361. {
  1362. if (dataMember.Equals(dataContract.Members[i], checkedContracts))
  1363. {
  1364. membersDictionary.Remove(dataMember.Name);
  1365. }
  1366. else
  1367. {
  1368. return false;
  1369. }
  1370. }
  1371. // otherwise save the non-matching datamembers for later verification
  1372. else
  1373. {
  1374. dataContractMembersList.Add(dataContract.Members[i]);
  1375. }
  1376. }
  1377. // check that datamembers left over from either datacontract are optional
  1378. if (!IsEveryDataMemberOptional(membersDictionary.Values))
  1379. return false;
  1380. if (!IsEveryDataMemberOptional(dataContractMembersList))
  1381. return false;
  1382. }
  1383. }
  1384. if (BaseContract == null)
  1385. return (dataContract.BaseContract == null);
  1386. else if (dataContract.BaseContract == null)
  1387. return false;
  1388. else
  1389. return BaseContract.Equals(dataContract.BaseContract, checkedContracts);
  1390. }
  1391. }
  1392. return false;
  1393. }
  1394. bool IsEveryDataMemberOptional(IEnumerable<DataMember> dataMembers)
  1395. {
  1396. foreach (DataMember dataMember in dataMembers)
  1397. {
  1398. if (dataMember.IsRequired)
  1399. return false;
  1400. }
  1401. return true;
  1402. }
  1403. public override int GetHashCode()
  1404. {
  1405. return base.GetHashCode();
  1406. }
  1407. internal class DataMemberComparer : IComparer<DataMember>
  1408. {
  1409. public int Compare(DataMember x, DataMember y)
  1410. {
  1411. int orderCompare = x.Order - y.Order;
  1412. if (orderCompare != 0)
  1413. return orderCompare;
  1414. return String.CompareOrdinal(x.Name, y.Name);
  1415. }
  1416. internal static DataMemberComparer Singleton = new DataMemberComparer();
  1417. }
  1418. }
  1419. }