CodeExporter.cs 101 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.Runtime.Serialization
  5. {
  6. using System;
  7. using System.CodeDom;
  8. using System.CodeDom.Compiler;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11. using System.ComponentModel;
  12. using System.Globalization;
  13. using System.Reflection;
  14. using System.Security;
  15. using System.Text;
  16. using System.Xml;
  17. using System.Xml.Schema;
  18. using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, DataContract>;
  19. class CodeExporter
  20. {
  21. DataContractSet dataContractSet;
  22. CodeCompileUnit codeCompileUnit;
  23. ImportOptions options;
  24. Dictionary<string, string> namespaces;
  25. Dictionary<string, string> clrNamespaces;
  26. [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
  27. + " data from being modified or leaked to other components in appdomain.")]
  28. static readonly string wildcardNamespaceMapping = "*";
  29. [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
  30. + " data from being modified or leaked to other components in appdomain.")]
  31. static readonly string typeNameFieldName = "typeName";
  32. [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
  33. + " data from being modified or leaked to other components in appdomain.")]
  34. static readonly object codeUserDataActualTypeKey = new object();
  35. [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
  36. + " data from being modified or leaked to other components in appdomain.")]
  37. static readonly object surrogateDataKey = typeof(IDataContractSurrogate);
  38. const int MaxIdentifierLength = 511;
  39. internal CodeExporter(DataContractSet dataContractSet, ImportOptions options, CodeCompileUnit codeCompileUnit)
  40. {
  41. this.dataContractSet = dataContractSet;
  42. this.codeCompileUnit = codeCompileUnit;
  43. AddReferencedAssembly(Assembly.GetExecutingAssembly());
  44. this.options = options;
  45. this.namespaces = new Dictionary<string, string>();
  46. this.clrNamespaces = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
  47. // Update namespace tables for DataContract(s) that are already processed
  48. foreach (KeyValuePair<XmlQualifiedName, DataContract> pair in dataContractSet)
  49. {
  50. DataContract dataContract = pair.Value;
  51. if (!(dataContract.IsBuiltInDataContract || dataContract is CollectionDataContract))
  52. {
  53. ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract);
  54. if (contractCodeDomInfo.IsProcessed && !contractCodeDomInfo.UsesWildcardNamespace)
  55. {
  56. string clrNamespace = contractCodeDomInfo.ClrNamespace;
  57. if (clrNamespace != null && !this.clrNamespaces.ContainsKey(clrNamespace))
  58. {
  59. this.clrNamespaces.Add(clrNamespace, dataContract.StableName.Namespace);
  60. this.namespaces.Add(dataContract.StableName.Namespace, clrNamespace);
  61. }
  62. }
  63. }
  64. }
  65. // Copy options.Namespaces to namespace tables
  66. if (this.options != null)
  67. {
  68. foreach (KeyValuePair<string, string> pair in options.Namespaces)
  69. {
  70. string dataContractNamespace = pair.Key;
  71. string clrNamespace = pair.Value;
  72. if (clrNamespace == null)
  73. clrNamespace = String.Empty;
  74. string currentDataContractNamespace;
  75. if (this.clrNamespaces.TryGetValue(clrNamespace, out currentDataContractNamespace))
  76. {
  77. if (dataContractNamespace != currentDataContractNamespace)
  78. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CLRNamespaceMappedMultipleTimes, currentDataContractNamespace, dataContractNamespace, clrNamespace)));
  79. }
  80. else
  81. this.clrNamespaces.Add(clrNamespace, dataContractNamespace);
  82. string currentClrNamespace;
  83. if (this.namespaces.TryGetValue(dataContractNamespace, out currentClrNamespace))
  84. {
  85. if (clrNamespace != currentClrNamespace)
  86. {
  87. this.namespaces.Remove(dataContractNamespace);
  88. this.namespaces.Add(dataContractNamespace, clrNamespace);
  89. }
  90. }
  91. else
  92. this.namespaces.Add(dataContractNamespace, clrNamespace);
  93. }
  94. }
  95. // Update namespace tables for pre-existing namespaces in CodeCompileUnit
  96. foreach (CodeNamespace codeNS in codeCompileUnit.Namespaces)
  97. {
  98. string ns = codeNS.Name ?? string.Empty;
  99. if (!this.clrNamespaces.ContainsKey(ns))
  100. {
  101. this.clrNamespaces.Add(ns, null);
  102. }
  103. if (ns.Length == 0)
  104. {
  105. foreach (CodeTypeDeclaration codeTypeDecl in codeNS.Types)
  106. {
  107. AddGlobalTypeName(codeTypeDecl.Name);
  108. }
  109. }
  110. }
  111. }
  112. void AddReferencedAssembly(Assembly assembly)
  113. {
  114. string assemblyName = System.IO.Path.GetFileName(assembly.Location);
  115. bool alreadyExisting = false;
  116. foreach (string existingName in this.codeCompileUnit.ReferencedAssemblies)
  117. {
  118. if (String.Compare(existingName, assemblyName, StringComparison.OrdinalIgnoreCase) == 0)
  119. {
  120. alreadyExisting = true;
  121. break;
  122. }
  123. }
  124. if (!alreadyExisting)
  125. this.codeCompileUnit.ReferencedAssemblies.Add(assemblyName);
  126. }
  127. bool GenerateSerializableTypes
  128. {
  129. get { return (options == null) ? false : options.GenerateSerializable; }
  130. }
  131. bool GenerateInternalTypes
  132. {
  133. get { return (options == null) ? false : options.GenerateInternal; }
  134. }
  135. bool EnableDataBinding
  136. {
  137. get { return (options == null) ? false : options.EnableDataBinding; }
  138. }
  139. CodeDomProvider CodeProvider
  140. {
  141. get { return (options == null) ? null : options.CodeProvider; }
  142. }
  143. bool SupportsDeclareEvents
  144. {
  145. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
  146. Safe = "Safe because it doesn't leak security sensitive information.")]
  147. [SecuritySafeCritical]
  148. get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.DeclareEvents); }
  149. }
  150. bool SupportsDeclareValueTypes
  151. {
  152. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
  153. Safe = "Safe because it doesn't leak security sensitive information.")]
  154. [SecuritySafeCritical]
  155. get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.DeclareValueTypes); }
  156. }
  157. bool SupportsGenericTypeReference
  158. {
  159. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
  160. Safe = "Safe because it doesn't leak security sensitive information.")]
  161. [SecuritySafeCritical]
  162. get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.GenericTypeReference); }
  163. }
  164. bool SupportsAssemblyAttributes
  165. {
  166. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
  167. Safe = "Safe because it doesn't leak security sensitive information.")]
  168. [SecuritySafeCritical]
  169. get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.AssemblyAttributes); }
  170. }
  171. bool SupportsPartialTypes
  172. {
  173. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
  174. Safe = "Safe because it doesn't leak security sensitive information.")]
  175. [SecuritySafeCritical]
  176. get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.PartialTypes); }
  177. }
  178. bool SupportsNestedTypes
  179. {
  180. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
  181. Safe = "Safe because it doesn't leak security sensitive information.")]
  182. [SecuritySafeCritical]
  183. get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.NestedTypes); }
  184. }
  185. string FileExtension
  186. {
  187. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.FileExtension property that has a LinkDemand.",
  188. Safe = "Safe because it doesn't leak security sensitive information.")]
  189. [SecuritySafeCritical]
  190. get { return (CodeProvider == null) ? String.Empty : CodeProvider.FileExtension; }
  191. }
  192. Dictionary<string, string> Namespaces
  193. {
  194. get { return namespaces; }
  195. }
  196. Dictionary<string, string> ClrNamespaces
  197. {
  198. get { return clrNamespaces; }
  199. }
  200. bool TryGetReferencedType(XmlQualifiedName stableName, DataContract dataContract, out Type type)
  201. {
  202. if (dataContract == null)
  203. {
  204. if (dataContractSet.TryGetReferencedCollectionType(stableName, dataContract, out type))
  205. return true;
  206. if (dataContractSet.TryGetReferencedType(stableName, dataContract, out type))
  207. {
  208. // enforce that collection types only be specified via ReferencedCollectionTypes
  209. if (CollectionDataContract.IsCollection(type))
  210. {
  211. type = null;
  212. return false;
  213. }
  214. return true;
  215. }
  216. return false;
  217. }
  218. else if (dataContract is CollectionDataContract)
  219. return dataContractSet.TryGetReferencedCollectionType(stableName, dataContract, out type);
  220. else
  221. {
  222. XmlDataContract xmlDataContract = dataContract as XmlDataContract;
  223. if (xmlDataContract != null && xmlDataContract.IsAnonymous)
  224. {
  225. stableName = SchemaImporter.ImportActualType(xmlDataContract.XsdType.Annotation, stableName, dataContract.StableName);
  226. }
  227. return dataContractSet.TryGetReferencedType(stableName, dataContract, out type);
  228. }
  229. }
  230. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the System.CodeDom.Compiler.CodeGenerator.ValidateIdentifiers(..) method that has a LinkDemand for FullTrust.")]
  231. [SecurityCritical]
  232. internal void Export()
  233. {
  234. try
  235. {
  236. foreach (KeyValuePair<XmlQualifiedName, DataContract> pair in dataContractSet)
  237. {
  238. DataContract dataContract = pair.Value;
  239. if (dataContract.IsBuiltInDataContract)
  240. continue;
  241. ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract);
  242. if (!contractCodeDomInfo.IsProcessed)
  243. {
  244. if (dataContract is ClassDataContract)
  245. {
  246. ClassDataContract classDataContract = (ClassDataContract)dataContract;
  247. if (classDataContract.IsISerializable)
  248. ExportISerializableDataContract(classDataContract, contractCodeDomInfo);
  249. else
  250. ExportClassDataContractHierarchy(classDataContract.StableName, classDataContract, contractCodeDomInfo, new Dictionary<XmlQualifiedName, object>());
  251. }
  252. else if (dataContract is CollectionDataContract)
  253. ExportCollectionDataContract((CollectionDataContract)dataContract, contractCodeDomInfo);
  254. else if (dataContract is EnumDataContract)
  255. ExportEnumDataContract((EnumDataContract)dataContract, contractCodeDomInfo);
  256. else if (dataContract is XmlDataContract)
  257. ExportXmlDataContract((XmlDataContract)dataContract, contractCodeDomInfo);
  258. else
  259. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(dataContract.GetType()), DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
  260. contractCodeDomInfo.IsProcessed = true;
  261. }
  262. }
  263. if (dataContractSet.DataContractSurrogate != null)
  264. {
  265. CodeNamespace[] namespaces = new CodeNamespace[codeCompileUnit.Namespaces.Count];
  266. codeCompileUnit.Namespaces.CopyTo(namespaces, 0);
  267. foreach (CodeNamespace codeNamespace in namespaces)
  268. InvokeProcessImportedType(codeNamespace.Types);
  269. }
  270. }
  271. finally
  272. {
  273. System.CodeDom.Compiler.CodeGenerator.ValidateIdentifiers(codeCompileUnit);
  274. }
  275. }
  276. void ExportClassDataContractHierarchy(XmlQualifiedName typeName, ClassDataContract classContract, ContractCodeDomInfo contractCodeDomInfo, Dictionary<XmlQualifiedName, object> contractNamesInHierarchy)
  277. {
  278. if (contractNamesInHierarchy.ContainsKey(classContract.StableName))
  279. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeCannotBeImported, typeName.Name, typeName.Namespace, SR.GetString(SR.CircularTypeReference, classContract.StableName.Name, classContract.StableName.Namespace))));
  280. contractNamesInHierarchy.Add(classContract.StableName, null);
  281. ClassDataContract baseContract = classContract.BaseContract;
  282. if (baseContract != null)
  283. {
  284. ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(baseContract);
  285. if (!baseContractCodeDomInfo.IsProcessed)
  286. {
  287. ExportClassDataContractHierarchy(typeName, baseContract, baseContractCodeDomInfo, contractNamesInHierarchy);
  288. baseContractCodeDomInfo.IsProcessed = true;
  289. }
  290. }
  291. ExportClassDataContract(classContract, contractCodeDomInfo);
  292. }
  293. void InvokeProcessImportedType(CollectionBase collection)
  294. {
  295. object[] objects = new object[collection.Count];
  296. ((ICollection)collection).CopyTo(objects, 0);
  297. foreach (object obj in objects)
  298. {
  299. CodeTypeDeclaration codeTypeDeclaration = obj as CodeTypeDeclaration;
  300. if (codeTypeDeclaration == null)
  301. continue;
  302. CodeTypeDeclaration newCodeTypeDeclaration = DataContractSurrogateCaller.ProcessImportedType(
  303. dataContractSet.DataContractSurrogate,
  304. codeTypeDeclaration,
  305. codeCompileUnit);
  306. if (newCodeTypeDeclaration != codeTypeDeclaration)
  307. {
  308. ((IList)collection).Remove(codeTypeDeclaration);
  309. if (newCodeTypeDeclaration != null)
  310. ((IList)collection).Add(newCodeTypeDeclaration);
  311. }
  312. if (newCodeTypeDeclaration != null)
  313. InvokeProcessImportedType(newCodeTypeDeclaration.Members);
  314. }
  315. }
  316. internal CodeTypeReference GetCodeTypeReference(DataContract dataContract)
  317. {
  318. if (dataContract.IsBuiltInDataContract)
  319. return GetCodeTypeReference(dataContract.UnderlyingType);
  320. ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract);
  321. GenerateType(dataContract, contractCodeDomInfo);
  322. return contractCodeDomInfo.TypeReference;
  323. }
  324. CodeTypeReference GetCodeTypeReference(Type type)
  325. {
  326. AddReferencedAssembly(type.Assembly);
  327. return new CodeTypeReference(type);
  328. }
  329. internal CodeTypeReference GetElementTypeReference(DataContract dataContract, bool isElementTypeNullable)
  330. {
  331. CodeTypeReference elementTypeReference = GetCodeTypeReference(dataContract);
  332. if (dataContract.IsValueType && isElementTypeNullable)
  333. elementTypeReference = WrapNullable(elementTypeReference);
  334. return elementTypeReference;
  335. }
  336. XmlQualifiedName GenericListName
  337. {
  338. get { return DataContract.GetStableName(Globals.TypeOfListGeneric); }
  339. }
  340. CollectionDataContract GenericListContract
  341. {
  342. get { return dataContractSet.GetDataContract(Globals.TypeOfListGeneric) as CollectionDataContract; }
  343. }
  344. XmlQualifiedName GenericDictionaryName
  345. {
  346. get { return DataContract.GetStableName(Globals.TypeOfDictionaryGeneric); }
  347. }
  348. CollectionDataContract GenericDictionaryContract
  349. {
  350. get { return dataContractSet.GetDataContract(Globals.TypeOfDictionaryGeneric) as CollectionDataContract; }
  351. }
  352. ContractCodeDomInfo GetContractCodeDomInfo(DataContract dataContract)
  353. {
  354. ContractCodeDomInfo contractCodeDomInfo = dataContractSet.GetContractCodeDomInfo(dataContract);
  355. if (contractCodeDomInfo == null)
  356. {
  357. contractCodeDomInfo = new ContractCodeDomInfo();
  358. dataContractSet.SetContractCodeDomInfo(dataContract, contractCodeDomInfo);
  359. }
  360. return contractCodeDomInfo;
  361. }
  362. void GenerateType(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo)
  363. {
  364. if (!contractCodeDomInfo.IsProcessed)
  365. {
  366. CodeTypeReference referencedType = GetReferencedType(dataContract);
  367. if (referencedType != null)
  368. {
  369. contractCodeDomInfo.TypeReference = referencedType;
  370. contractCodeDomInfo.ReferencedTypeExists = true;
  371. }
  372. else
  373. {
  374. CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration;
  375. if (type == null)
  376. {
  377. string clrNamespace = GetClrNamespace(dataContract, contractCodeDomInfo);
  378. CodeNamespace ns = GetCodeNamespace(clrNamespace, dataContract.StableName.Namespace, contractCodeDomInfo);
  379. type = GetNestedType(dataContract, contractCodeDomInfo);
  380. if (type == null)
  381. {
  382. string typeName = XmlConvert.DecodeName(dataContract.StableName.Name);
  383. typeName = GetClrIdentifier(typeName, Globals.DefaultTypeName);
  384. if (NamespaceContainsType(ns, typeName) || GlobalTypeNameConflicts(clrNamespace, typeName))
  385. {
  386. for (int i = 1;; i++)
  387. {
  388. string uniqueName = AppendToValidClrIdentifier(typeName, i.ToString(NumberFormatInfo.InvariantInfo));
  389. if (!NamespaceContainsType(ns, uniqueName) && !GlobalTypeNameConflicts(clrNamespace, uniqueName))
  390. {
  391. typeName = uniqueName;
  392. break;
  393. }
  394. if (i == Int32.MaxValue)
  395. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CannotComputeUniqueName, typeName)));
  396. }
  397. }
  398. type = CreateTypeDeclaration(typeName, dataContract);
  399. ns.Types.Add(type);
  400. if (string.IsNullOrEmpty(clrNamespace))
  401. {
  402. AddGlobalTypeName(typeName);
  403. }
  404. contractCodeDomInfo.TypeReference = new CodeTypeReference((clrNamespace == null || clrNamespace.Length == 0) ? typeName : clrNamespace + "." + typeName);
  405. if (GenerateInternalTypes)
  406. type.TypeAttributes = TypeAttributes.NotPublic;
  407. else
  408. type.TypeAttributes = TypeAttributes.Public;
  409. }
  410. if (dataContractSet.DataContractSurrogate != null)
  411. type.UserData.Add(surrogateDataKey, dataContractSet.GetSurrogateData(dataContract));
  412. contractCodeDomInfo.TypeDeclaration = type;
  413. }
  414. }
  415. }
  416. }
  417. CodeTypeDeclaration GetNestedType(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo)
  418. {
  419. if (!SupportsNestedTypes)
  420. return null;
  421. string originalName = dataContract.StableName.Name;
  422. int nestedTypeIndex = originalName.LastIndexOf('.');
  423. if (nestedTypeIndex <= 0)
  424. return null;
  425. string containingTypeName = originalName.Substring(0, nestedTypeIndex);
  426. DataContract containingDataContract = dataContractSet[new XmlQualifiedName(containingTypeName, dataContract.StableName.Namespace)];
  427. if (containingDataContract == null)
  428. return null;
  429. string nestedTypeName = XmlConvert.DecodeName(originalName.Substring(nestedTypeIndex + 1));
  430. nestedTypeName = GetClrIdentifier(nestedTypeName, Globals.DefaultTypeName);
  431. ContractCodeDomInfo containingContractCodeDomInfo = GetContractCodeDomInfo(containingDataContract);
  432. GenerateType(containingDataContract, containingContractCodeDomInfo);
  433. if (containingContractCodeDomInfo.ReferencedTypeExists)
  434. return null;
  435. CodeTypeDeclaration containingType = containingContractCodeDomInfo.TypeDeclaration;
  436. if (TypeContainsNestedType(containingType, nestedTypeName))
  437. {
  438. for (int i = 1;; i++)
  439. {
  440. string uniqueName = AppendToValidClrIdentifier(nestedTypeName, i.ToString(NumberFormatInfo.InvariantInfo));
  441. if (!TypeContainsNestedType(containingType, uniqueName))
  442. {
  443. nestedTypeName = uniqueName;
  444. break;
  445. }
  446. }
  447. }
  448. CodeTypeDeclaration type = CreateTypeDeclaration(nestedTypeName, dataContract);
  449. containingType.Members.Add(type);
  450. contractCodeDomInfo.TypeReference = new CodeTypeReference(containingContractCodeDomInfo.TypeReference.BaseType + "+" + nestedTypeName);
  451. if (GenerateInternalTypes)
  452. type.TypeAttributes = TypeAttributes.NestedAssembly;
  453. else
  454. type.TypeAttributes = TypeAttributes.NestedPublic;
  455. return type;
  456. }
  457. static CodeTypeDeclaration CreateTypeDeclaration(string typeName, DataContract dataContract)
  458. {
  459. CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeName);
  460. CodeAttributeDeclaration debuggerStepThroughAttribute = new CodeAttributeDeclaration(typeof(System.Diagnostics.DebuggerStepThroughAttribute).FullName);
  461. CodeAttributeDeclaration generatedCodeAttribute = new CodeAttributeDeclaration(typeof(GeneratedCodeAttribute).FullName);
  462. AssemblyName assemblyName = Assembly.GetExecutingAssembly().GetName();
  463. generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Name)));
  464. generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Version.ToString())));
  465. // System.Diagnostics.DebuggerStepThroughAttribute not allowed on enums
  466. // ensure that the attribute is only generated on types that are not enums
  467. EnumDataContract enumDataContract = dataContract as EnumDataContract;
  468. if (enumDataContract == null)
  469. {
  470. typeDecl.CustomAttributes.Add(debuggerStepThroughAttribute);
  471. }
  472. typeDecl.CustomAttributes.Add(generatedCodeAttribute);
  473. return typeDecl;
  474. }
  475. [Fx.Tag.SecurityNote(Critical = "Sets critical properties on internal XmlDataContract.",
  476. Safe = "Called during schema import/code generation.")]
  477. [SecuritySafeCritical]
  478. CodeTypeReference GetReferencedType(DataContract dataContract)
  479. {
  480. Type type = null;
  481. CodeTypeReference typeReference = GetSurrogatedTypeReference(dataContract);
  482. if (typeReference != null)
  483. return typeReference;
  484. if (TryGetReferencedType(dataContract.StableName, dataContract, out type)
  485. && !type.IsGenericTypeDefinition && !type.ContainsGenericParameters)
  486. {
  487. if (dataContract is XmlDataContract)
  488. {
  489. if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
  490. {
  491. XmlDataContract xmlContract = (XmlDataContract)dataContract;
  492. if (xmlContract.IsTypeDefinedOnImport)
  493. {
  494. if (!xmlContract.Equals(dataContractSet.GetDataContract(type)))
  495. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch, type.AssemblyQualifiedName, dataContract.StableName.Name, dataContract.StableName.Namespace)));
  496. }
  497. else
  498. {
  499. xmlContract.IsValueType = type.IsValueType;
  500. xmlContract.IsTypeDefinedOnImport = true;
  501. }
  502. return GetCodeTypeReference(type);
  503. }
  504. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeMustBeIXmlSerializable, DataContract.GetClrTypeFullName(type), DataContract.GetClrTypeFullName(Globals.TypeOfIXmlSerializable), dataContract.StableName.Name, dataContract.StableName.Namespace)));
  505. }
  506. DataContract referencedContract = dataContractSet.GetDataContract(type);
  507. if (referencedContract.Equals(dataContract))
  508. {
  509. typeReference = GetCodeTypeReference(type);
  510. typeReference.UserData.Add(codeUserDataActualTypeKey, type);
  511. return typeReference;
  512. }
  513. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch, type.AssemblyQualifiedName, dataContract.StableName.Name, dataContract.StableName.Namespace)));
  514. }
  515. else if (dataContract.GenericInfo != null)
  516. {
  517. DataContract referencedContract;
  518. XmlQualifiedName genericStableName = dataContract.GenericInfo.GetExpandedStableName();
  519. if (genericStableName != dataContract.StableName)
  520. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericTypeNameMismatch, dataContract.StableName.Name, dataContract.StableName.Namespace, genericStableName.Name, genericStableName.Namespace)));
  521. typeReference = GetReferencedGenericType(dataContract.GenericInfo, out referencedContract);
  522. if (referencedContract != null && !referencedContract.Equals(dataContract))
  523. {
  524. type = (Type)typeReference.UserData[codeUserDataActualTypeKey];
  525. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch,
  526. type.AssemblyQualifiedName,
  527. referencedContract.StableName.Name,
  528. referencedContract.StableName.Namespace)));
  529. }
  530. return typeReference;
  531. }
  532. return GetReferencedCollectionType(dataContract as CollectionDataContract);
  533. }
  534. CodeTypeReference GetReferencedCollectionType(CollectionDataContract collectionContract)
  535. {
  536. if (collectionContract == null)
  537. return null;
  538. if (HasDefaultCollectionNames(collectionContract))
  539. {
  540. CodeTypeReference typeReference;
  541. if (!TryGetReferencedDictionaryType(collectionContract, out typeReference))
  542. {
  543. DataContract itemContract = collectionContract.ItemContract;
  544. if (collectionContract.IsDictionary)
  545. {
  546. GenerateKeyValueType(itemContract as ClassDataContract);
  547. }
  548. bool isItemTypeNullable = collectionContract.IsItemTypeNullable;
  549. if (!TryGetReferencedListType(itemContract, isItemTypeNullable, out typeReference))
  550. typeReference = new CodeTypeReference(GetElementTypeReference(itemContract, isItemTypeNullable), 1);
  551. }
  552. return typeReference;
  553. }
  554. return null;
  555. }
  556. bool HasDefaultCollectionNames(CollectionDataContract collectionContract)
  557. {
  558. DataContract itemContract = collectionContract.ItemContract;
  559. if (collectionContract.ItemName != itemContract.StableName.Name)
  560. return false;
  561. if (collectionContract.IsDictionary &&
  562. (collectionContract.KeyName != Globals.KeyLocalName || collectionContract.ValueName != Globals.ValueLocalName))
  563. return false;
  564. XmlQualifiedName expectedType = itemContract.GetArrayTypeName(collectionContract.IsItemTypeNullable);
  565. return (collectionContract.StableName.Name == expectedType.Name && collectionContract.StableName.Namespace == expectedType.Namespace);
  566. }
  567. bool TryGetReferencedDictionaryType(CollectionDataContract collectionContract, out CodeTypeReference typeReference)
  568. {
  569. // Check if it is a dictionary and use referenced dictionary type if present
  570. if (collectionContract.IsDictionary
  571. && SupportsGenericTypeReference)
  572. {
  573. Type type;
  574. if (!TryGetReferencedType(GenericDictionaryName, GenericDictionaryContract, out type))
  575. type = Globals.TypeOfDictionaryGeneric;
  576. ClassDataContract itemContract = collectionContract.ItemContract as ClassDataContract;
  577. DataMember keyMember = itemContract.Members[0];
  578. DataMember valueMember = itemContract.Members[1];
  579. CodeTypeReference keyTypeReference = GetElementTypeReference(keyMember.MemberTypeContract, keyMember.IsNullable);
  580. CodeTypeReference valueTypeReference = GetElementTypeReference(valueMember.MemberTypeContract, valueMember.IsNullable);
  581. if (keyTypeReference != null && valueTypeReference != null)
  582. {
  583. typeReference = GetCodeTypeReference(type);
  584. typeReference.TypeArguments.Add(keyTypeReference);
  585. typeReference.TypeArguments.Add(valueTypeReference);
  586. return true;
  587. }
  588. }
  589. typeReference = null;
  590. return false;
  591. }
  592. bool TryGetReferencedListType(DataContract itemContract, bool isItemTypeNullable, out CodeTypeReference typeReference)
  593. {
  594. Type type;
  595. if (SupportsGenericTypeReference && TryGetReferencedType(GenericListName, GenericListContract, out type))
  596. {
  597. typeReference = GetCodeTypeReference(type);
  598. typeReference.TypeArguments.Add(GetElementTypeReference(itemContract, isItemTypeNullable));
  599. return true;
  600. }
  601. typeReference = null;
  602. return false;
  603. }
  604. CodeTypeReference GetSurrogatedTypeReference(DataContract dataContract)
  605. {
  606. IDataContractSurrogate dataContractSurrogate = this.dataContractSet.DataContractSurrogate;
  607. if (dataContractSurrogate != null)
  608. {
  609. Type type = DataContractSurrogateCaller.GetReferencedTypeOnImport(
  610. dataContractSurrogate,
  611. dataContract.StableName.Name,
  612. dataContract.StableName.Namespace,
  613. dataContractSet.GetSurrogateData(dataContract));
  614. if (type != null)
  615. {
  616. CodeTypeReference typeReference = GetCodeTypeReference(type);
  617. typeReference.UserData.Add(codeUserDataActualTypeKey, type);
  618. return typeReference;
  619. }
  620. }
  621. return null;
  622. }
  623. CodeTypeReference GetReferencedGenericType(GenericInfo genInfo, out DataContract dataContract)
  624. {
  625. dataContract = null;
  626. if (!SupportsGenericTypeReference)
  627. return null;
  628. Type type;
  629. if (!TryGetReferencedType(genInfo.StableName, null, out type))
  630. {
  631. if (genInfo.Parameters != null)
  632. return null;
  633. dataContract = dataContractSet[genInfo.StableName];
  634. if (dataContract == null)
  635. return null;
  636. if (dataContract.GenericInfo != null)
  637. return null;
  638. return GetCodeTypeReference(dataContract);
  639. }
  640. bool enableStructureCheck = (type != Globals.TypeOfNullable);
  641. CodeTypeReference typeReference = GetCodeTypeReference(type);
  642. typeReference.UserData.Add(codeUserDataActualTypeKey, type);
  643. if (genInfo.Parameters != null)
  644. {
  645. DataContract[] paramContracts = new DataContract[genInfo.Parameters.Count];
  646. for (int i = 0; i < genInfo.Parameters.Count; i++)
  647. {
  648. GenericInfo paramInfo = genInfo.Parameters[i];
  649. XmlQualifiedName stableName = paramInfo.GetExpandedStableName();
  650. DataContract paramContract = dataContractSet[stableName];
  651. CodeTypeReference paramTypeReference;
  652. bool isParamValueType;
  653. if (paramContract != null)
  654. {
  655. paramTypeReference = GetCodeTypeReference(paramContract);
  656. isParamValueType = paramContract.IsValueType;
  657. }
  658. else
  659. {
  660. paramTypeReference = GetReferencedGenericType(paramInfo, out paramContract);
  661. isParamValueType = (paramTypeReference != null && paramTypeReference.ArrayRank == 0); // only value type information we can get from CodeTypeReference
  662. }
  663. paramContracts[i] = paramContract;
  664. if (paramContract == null)
  665. enableStructureCheck = false;
  666. if (paramTypeReference == null)
  667. return null;
  668. if (type == Globals.TypeOfNullable && !isParamValueType)
  669. return paramTypeReference;
  670. else
  671. typeReference.TypeArguments.Add(paramTypeReference);
  672. }
  673. if (enableStructureCheck)
  674. dataContract = DataContract.GetDataContract(type).BindGenericParameters(paramContracts, new Dictionary<DataContract, DataContract>());
  675. }
  676. return typeReference;
  677. }
  678. bool NamespaceContainsType(CodeNamespace ns, string typeName)
  679. {
  680. foreach (CodeTypeDeclaration type in ns.Types)
  681. {
  682. if (String.Compare(typeName, type.Name, StringComparison.OrdinalIgnoreCase) == 0)
  683. return true;
  684. }
  685. return false;
  686. }
  687. bool GlobalTypeNameConflicts(string clrNamespace, string typeName)
  688. {
  689. return (string.IsNullOrEmpty(clrNamespace) && this.clrNamespaces.ContainsKey(typeName));
  690. }
  691. void AddGlobalTypeName(string typeName)
  692. {
  693. if (!this.clrNamespaces.ContainsKey(typeName))
  694. {
  695. this.clrNamespaces.Add(typeName, null);
  696. }
  697. }
  698. bool TypeContainsNestedType(CodeTypeDeclaration containingType, string typeName)
  699. {
  700. foreach (CodeTypeMember member in containingType.Members)
  701. {
  702. if (member is CodeTypeDeclaration)
  703. {
  704. if (String.Compare(typeName, ((CodeTypeDeclaration)member).Name, StringComparison.OrdinalIgnoreCase) == 0)
  705. return true;
  706. }
  707. }
  708. return false;
  709. }
  710. string GetNameForAttribute(string name)
  711. {
  712. string decodedName = XmlConvert.DecodeName(name);
  713. if (string.CompareOrdinal(name, decodedName) == 0)
  714. return name;
  715. string reencodedName = DataContract.EncodeLocalName(decodedName);
  716. return (string.CompareOrdinal(name, reencodedName) == 0) ? decodedName : name;
  717. }
  718. void AddSerializableAttribute(bool generateSerializable, CodeTypeDeclaration type, ContractCodeDomInfo contractCodeDomInfo)
  719. {
  720. if (generateSerializable)
  721. {
  722. type.CustomAttributes.Add(SerializableAttribute);
  723. AddImportStatement(Globals.TypeOfSerializableAttribute.Namespace, contractCodeDomInfo.CodeNamespace);
  724. }
  725. }
  726. void ExportClassDataContract(ClassDataContract classDataContract, ContractCodeDomInfo contractCodeDomInfo)
  727. {
  728. GenerateType(classDataContract, contractCodeDomInfo);
  729. if (contractCodeDomInfo.ReferencedTypeExists)
  730. return;
  731. CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration;
  732. if (SupportsPartialTypes)
  733. type.IsPartial = true;
  734. if (classDataContract.IsValueType && SupportsDeclareValueTypes)
  735. type.IsStruct = true;
  736. else
  737. type.IsClass = true;
  738. string dataContractName = GetNameForAttribute(classDataContract.StableName.Name);
  739. CodeAttributeDeclaration dataContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataContractAttribute));
  740. dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName)));
  741. dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(classDataContract.StableName.Namespace)));
  742. if (classDataContract.IsReference != Globals.DefaultIsReference)
  743. dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsReferenceProperty, new CodePrimitiveExpression(classDataContract.IsReference)));
  744. type.CustomAttributes.Add(dataContractAttribute);
  745. AddImportStatement(Globals.TypeOfDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace);
  746. AddSerializableAttribute(GenerateSerializableTypes, type, contractCodeDomInfo);
  747. AddKnownTypes(classDataContract, contractCodeDomInfo);
  748. bool raisePropertyChanged = EnableDataBinding && SupportsDeclareEvents;
  749. if (classDataContract.BaseContract == null)
  750. {
  751. if (!type.IsStruct)
  752. type.BaseTypes.Add(Globals.TypeOfObject);
  753. AddExtensionData(contractCodeDomInfo);
  754. AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct);
  755. }
  756. else
  757. {
  758. ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(classDataContract.BaseContract);
  759. Fx.Assert(baseContractCodeDomInfo.IsProcessed, "Cannot generate code for type if code for base type has not been generated");
  760. type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference);
  761. AddBaseMemberNames(baseContractCodeDomInfo, contractCodeDomInfo);
  762. if (baseContractCodeDomInfo.ReferencedTypeExists)
  763. {
  764. Type actualType = (Type)baseContractCodeDomInfo.TypeReference.UserData[codeUserDataActualTypeKey];
  765. ThrowIfReferencedBaseTypeSealed(actualType, classDataContract);
  766. if (!Globals.TypeOfIExtensibleDataObject.IsAssignableFrom(actualType))
  767. AddExtensionData(contractCodeDomInfo);
  768. if (!Globals.TypeOfIPropertyChange.IsAssignableFrom(actualType))
  769. {
  770. AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct);
  771. }
  772. else
  773. {
  774. raisePropertyChanged = false;
  775. }
  776. }
  777. }
  778. if (classDataContract.Members != null)
  779. {
  780. for (int i = 0; i < classDataContract.Members.Count; i++)
  781. {
  782. DataMember dataMember = classDataContract.Members[i];
  783. CodeTypeReference memberType = GetElementTypeReference(dataMember.MemberTypeContract,
  784. (dataMember.IsNullable && dataMember.MemberTypeContract.IsValueType));
  785. string dataMemberName = GetNameForAttribute(dataMember.Name);
  786. string propertyName = GetMemberName(dataMemberName, contractCodeDomInfo);
  787. string fieldName = GetMemberName(AppendToValidClrIdentifier(propertyName, Globals.DefaultFieldSuffix), contractCodeDomInfo);
  788. CodeMemberField field = new CodeMemberField();
  789. field.Type = memberType;
  790. field.Name = fieldName;
  791. field.Attributes = MemberAttributes.Private;
  792. CodeMemberProperty property = CreateProperty(memberType, propertyName, fieldName, dataMember.MemberTypeContract.IsValueType && SupportsDeclareValueTypes, raisePropertyChanged);
  793. if (dataContractSet.DataContractSurrogate != null)
  794. property.UserData.Add(surrogateDataKey, dataContractSet.GetSurrogateData(dataMember));
  795. CodeAttributeDeclaration dataMemberAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataMemberAttribute));
  796. if (dataMemberName != property.Name)
  797. dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataMemberName)));
  798. if (dataMember.IsRequired != Globals.DefaultIsRequired)
  799. dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsRequiredProperty, new CodePrimitiveExpression(dataMember.IsRequired)));
  800. if (dataMember.EmitDefaultValue != Globals.DefaultEmitDefaultValue)
  801. dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.EmitDefaultValueProperty, new CodePrimitiveExpression(dataMember.EmitDefaultValue)));
  802. if (dataMember.Order != Globals.DefaultOrder)
  803. dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.OrderProperty, new CodePrimitiveExpression(dataMember.Order)));
  804. property.CustomAttributes.Add(dataMemberAttribute);
  805. if (GenerateSerializableTypes && !dataMember.IsRequired)
  806. {
  807. CodeAttributeDeclaration optionalFieldAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfOptionalFieldAttribute));
  808. field.CustomAttributes.Add(optionalFieldAttribute);
  809. }
  810. type.Members.Add(field);
  811. type.Members.Add(property);
  812. }
  813. }
  814. }
  815. bool CanDeclareAssemblyAttribute(ContractCodeDomInfo contractCodeDomInfo)
  816. {
  817. return SupportsAssemblyAttributes && !contractCodeDomInfo.UsesWildcardNamespace;
  818. }
  819. bool NeedsExplicitNamespace(string dataContractNamespace, string clrNamespace)
  820. {
  821. return (DataContract.GetDefaultStableNamespace(clrNamespace) != dataContractNamespace);
  822. }
  823. internal ICollection<CodeTypeReference> GetKnownTypeReferences(DataContract dataContract)
  824. {
  825. DataContractDictionary knownTypeDictionary = GetKnownTypeContracts(dataContract);
  826. if (knownTypeDictionary == null)
  827. return null;
  828. ICollection<DataContract> knownTypeContracts = knownTypeDictionary.Values;
  829. if (knownTypeContracts == null || knownTypeContracts.Count == 0)
  830. return null;
  831. List<CodeTypeReference> knownTypeReferences = new List<CodeTypeReference>();
  832. foreach (DataContract knownTypeContract in knownTypeContracts)
  833. {
  834. knownTypeReferences.Add(GetCodeTypeReference(knownTypeContract));
  835. }
  836. return knownTypeReferences;
  837. }
  838. DataContractDictionary GetKnownTypeContracts(DataContract dataContract)
  839. {
  840. if (dataContractSet.KnownTypesForObject != null && SchemaImporter.IsObjectContract(dataContract))
  841. {
  842. return dataContractSet.KnownTypesForObject;
  843. }
  844. else if (dataContract is ClassDataContract)
  845. {
  846. ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract);
  847. if (!contractCodeDomInfo.IsProcessed)
  848. GenerateType(dataContract, contractCodeDomInfo);
  849. if (contractCodeDomInfo.ReferencedTypeExists)
  850. return GetKnownTypeContracts((ClassDataContract)dataContract, new Dictionary<DataContract, object>());
  851. }
  852. return null;
  853. }
  854. DataContractDictionary GetKnownTypeContracts(ClassDataContract dataContract, Dictionary<DataContract, object> handledContracts)
  855. {
  856. if (handledContracts.ContainsKey(dataContract))
  857. return dataContract.KnownDataContracts;
  858. handledContracts.Add(dataContract, null);
  859. if (dataContract.Members != null)
  860. {
  861. bool objectMemberHandled = false;
  862. foreach (DataMember dataMember in dataContract.Members)
  863. {
  864. DataContract memberContract = dataMember.MemberTypeContract;
  865. if (!objectMemberHandled && dataContractSet.KnownTypesForObject != null && SchemaImporter.IsObjectContract(memberContract))
  866. {
  867. AddKnownTypeContracts(dataContract, dataContractSet.KnownTypesForObject);
  868. objectMemberHandled = true;
  869. }
  870. else if (memberContract is ClassDataContract)
  871. {
  872. ContractCodeDomInfo memberCodeDomInfo = GetContractCodeDomInfo(memberContract);
  873. if (!memberCodeDomInfo.IsProcessed)
  874. GenerateType(memberContract, memberCodeDomInfo);
  875. if (memberCodeDomInfo.ReferencedTypeExists)
  876. {
  877. AddKnownTypeContracts(dataContract, GetKnownTypeContracts((ClassDataContract)memberContract, handledContracts));
  878. }
  879. }
  880. }
  881. }
  882. return dataContract.KnownDataContracts;
  883. }
  884. [Fx.Tag.SecurityNote(Critical = "Sets critical properties on internal DataContract.",
  885. Safe = "Called during schema import/code generation.")]
  886. [SecuritySafeCritical]
  887. void AddKnownTypeContracts(ClassDataContract dataContract, DataContractDictionary knownContracts)
  888. {
  889. if (knownContracts == null || knownContracts.Count == 0)
  890. return;
  891. if (dataContract.KnownDataContracts == null)
  892. dataContract.KnownDataContracts = new DataContractDictionary();
  893. foreach (KeyValuePair<XmlQualifiedName, DataContract> pair in knownContracts)
  894. {
  895. if (dataContract.StableName != pair.Key && !dataContract.KnownDataContracts.ContainsKey(pair.Key) && !pair.Value.IsBuiltInDataContract)
  896. dataContract.KnownDataContracts.Add(pair.Key, pair.Value);
  897. }
  898. }
  899. void AddKnownTypes(ClassDataContract dataContract, ContractCodeDomInfo contractCodeDomInfo)
  900. {
  901. DataContractDictionary knownContractDictionary = GetKnownTypeContracts(dataContract, new Dictionary<DataContract, object>());
  902. if (knownContractDictionary == null || knownContractDictionary.Count == 0)
  903. return;
  904. ICollection<DataContract> knownTypeContracts = knownContractDictionary.Values;
  905. foreach (DataContract knownTypeContract in knownTypeContracts)
  906. {
  907. CodeAttributeDeclaration knownTypeAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfKnownTypeAttribute));
  908. knownTypeAttribute.Arguments.Add(new CodeAttributeArgument(new CodeTypeOfExpression(GetCodeTypeReference(knownTypeContract))));
  909. contractCodeDomInfo.TypeDeclaration.CustomAttributes.Add(knownTypeAttribute);
  910. }
  911. AddImportStatement(Globals.TypeOfKnownTypeAttribute.Namespace, contractCodeDomInfo.CodeNamespace);
  912. }
  913. CodeTypeReference WrapNullable(CodeTypeReference memberType)
  914. {
  915. if (!SupportsGenericTypeReference)
  916. return memberType;
  917. CodeTypeReference nullableOfMemberType = GetCodeTypeReference(Globals.TypeOfNullable);
  918. nullableOfMemberType.TypeArguments.Add(memberType);
  919. return nullableOfMemberType;
  920. }
  921. void AddExtensionData(ContractCodeDomInfo contractCodeDomInfo)
  922. {
  923. if (contractCodeDomInfo != null && contractCodeDomInfo.TypeDeclaration != null)
  924. {
  925. CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration;
  926. type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfIExtensibleDataObject));
  927. CodeMemberField extensionDataObjectField = ExtensionDataObjectField;
  928. if (GenerateSerializableTypes)
  929. {
  930. CodeAttributeDeclaration nonSerializedAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfNonSerializedAttribute));
  931. extensionDataObjectField.CustomAttributes.Add(nonSerializedAttribute);
  932. }
  933. type.Members.Add(extensionDataObjectField);
  934. contractCodeDomInfo.GetMemberNames().Add(extensionDataObjectField.Name, null);
  935. CodeMemberProperty extensionDataObjectProperty = ExtensionDataObjectProperty;
  936. type.Members.Add(extensionDataObjectProperty);
  937. contractCodeDomInfo.GetMemberNames().Add(extensionDataObjectProperty.Name, null);
  938. }
  939. }
  940. void AddPropertyChangedNotifier(ContractCodeDomInfo contractCodeDomInfo, bool isValueType)
  941. {
  942. if (EnableDataBinding && SupportsDeclareEvents && contractCodeDomInfo != null && contractCodeDomInfo.TypeDeclaration != null)
  943. {
  944. CodeTypeDeclaration codeTypeDeclaration = contractCodeDomInfo.TypeDeclaration;
  945. codeTypeDeclaration.BaseTypes.Add(CodeTypeIPropertyChange);
  946. CodeMemberEvent memberEvent = PropertyChangedEvent;
  947. codeTypeDeclaration.Members.Add(memberEvent);
  948. CodeMemberMethod raisePropertyChangedEventMethod = RaisePropertyChangedEventMethod;
  949. if (!isValueType)
  950. raisePropertyChangedEventMethod.Attributes |= MemberAttributes.Family;
  951. codeTypeDeclaration.Members.Add(raisePropertyChangedEventMethod);
  952. contractCodeDomInfo.GetMemberNames().Add(memberEvent.Name, null);
  953. contractCodeDomInfo.GetMemberNames().Add(raisePropertyChangedEventMethod.Name, null);
  954. }
  955. }
  956. void ThrowIfReferencedBaseTypeSealed(Type baseType, DataContract dataContract)
  957. {
  958. if (baseType.IsSealed)
  959. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CannotDeriveFromSealedReferenceType, dataContract.StableName.Name, dataContract.StableName.Namespace, DataContract.GetClrTypeFullName(baseType))));
  960. }
  961. void ExportEnumDataContract(EnumDataContract enumDataContract, ContractCodeDomInfo contractCodeDomInfo)
  962. {
  963. GenerateType(enumDataContract, contractCodeDomInfo);
  964. if (contractCodeDomInfo.ReferencedTypeExists)
  965. return;
  966. CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration;
  967. type.IsEnum = true;
  968. type.BaseTypes.Add(EnumDataContract.GetBaseType(enumDataContract.BaseContractName));
  969. if (enumDataContract.IsFlags)
  970. {
  971. type.CustomAttributes.Add(new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfFlagsAttribute)));
  972. AddImportStatement(Globals.TypeOfFlagsAttribute.Namespace, contractCodeDomInfo.CodeNamespace);
  973. }
  974. string dataContractName = GetNameForAttribute(enumDataContract.StableName.Name);
  975. CodeAttributeDeclaration dataContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataContractAttribute));
  976. dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName)));
  977. dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(enumDataContract.StableName.Namespace)));
  978. type.CustomAttributes.Add(dataContractAttribute);
  979. AddImportStatement(Globals.TypeOfDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace);
  980. if (enumDataContract.Members != null)
  981. {
  982. for (int i = 0; i < enumDataContract.Members.Count; i++)
  983. {
  984. string stringValue = enumDataContract.Members[i].Name;
  985. long longValue = enumDataContract.Values[i];
  986. CodeMemberField enumMember = new CodeMemberField();
  987. if (enumDataContract.IsULong)
  988. enumMember.InitExpression = new CodeSnippetExpression(enumDataContract.GetStringFromEnumValue(longValue));
  989. else
  990. enumMember.InitExpression = new CodePrimitiveExpression(longValue);
  991. enumMember.Name = GetMemberName(stringValue, contractCodeDomInfo);
  992. CodeAttributeDeclaration enumMemberAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfEnumMemberAttribute));
  993. if (enumMember.Name != stringValue)
  994. enumMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ValueProperty, new CodePrimitiveExpression(stringValue)));
  995. enumMember.CustomAttributes.Add(enumMemberAttribute);
  996. type.Members.Add(enumMember);
  997. }
  998. }
  999. }
  1000. void ExportISerializableDataContract(ClassDataContract dataContract, ContractCodeDomInfo contractCodeDomInfo)
  1001. {
  1002. GenerateType(dataContract, contractCodeDomInfo);
  1003. if (contractCodeDomInfo.ReferencedTypeExists)
  1004. return;
  1005. if (DataContract.GetDefaultStableNamespace(contractCodeDomInfo.ClrNamespace) != dataContract.StableName.Namespace)
  1006. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidClrNamespaceGeneratedForISerializable, dataContract.StableName.Name, dataContract.StableName.Namespace, DataContract.GetDataContractNamespaceFromUri(dataContract.StableName.Namespace), contractCodeDomInfo.ClrNamespace)));
  1007. string dataContractName = GetNameForAttribute(dataContract.StableName.Name);
  1008. int nestedTypeIndex = dataContractName.LastIndexOf('.');
  1009. string expectedName = (nestedTypeIndex <= 0 || nestedTypeIndex == dataContractName.Length - 1) ? dataContractName : dataContractName.Substring(nestedTypeIndex + 1);
  1010. if (contractCodeDomInfo.TypeDeclaration.Name != expectedName)
  1011. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidClrNameGeneratedForISerializable, dataContract.StableName.Name, dataContract.StableName.Namespace, contractCodeDomInfo.TypeDeclaration.Name)));
  1012. CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration;
  1013. if (SupportsPartialTypes)
  1014. type.IsPartial = true;
  1015. if (dataContract.IsValueType && SupportsDeclareValueTypes)
  1016. type.IsStruct = true;
  1017. else
  1018. type.IsClass = true;
  1019. AddSerializableAttribute(true /*generateSerializable*/, type, contractCodeDomInfo);
  1020. AddKnownTypes(dataContract, contractCodeDomInfo);
  1021. if (dataContract.BaseContract == null)
  1022. {
  1023. if (!type.IsStruct)
  1024. type.BaseTypes.Add(Globals.TypeOfObject);
  1025. type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfISerializable));
  1026. type.Members.Add(ISerializableBaseConstructor);
  1027. type.Members.Add(SerializationInfoField);
  1028. type.Members.Add(SerializationInfoProperty);
  1029. type.Members.Add(GetObjectDataMethod);
  1030. AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct);
  1031. }
  1032. else
  1033. {
  1034. ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(dataContract.BaseContract);
  1035. GenerateType(dataContract.BaseContract, baseContractCodeDomInfo);
  1036. type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference);
  1037. if (baseContractCodeDomInfo.ReferencedTypeExists)
  1038. {
  1039. Type actualType = (Type)baseContractCodeDomInfo.TypeReference.UserData[codeUserDataActualTypeKey];
  1040. ThrowIfReferencedBaseTypeSealed(actualType, dataContract);
  1041. }
  1042. type.Members.Add(ISerializableDerivedConstructor);
  1043. }
  1044. }
  1045. void GenerateKeyValueType(ClassDataContract keyValueContract)
  1046. {
  1047. // Add code for KeyValue item type in the case where its usage is limited to dictionary
  1048. // and dictionary is not found in referenced types
  1049. if (keyValueContract != null && dataContractSet[keyValueContract.StableName] == null)
  1050. {
  1051. ContractCodeDomInfo contractCodeDomInfo = dataContractSet.GetContractCodeDomInfo(keyValueContract);
  1052. if (contractCodeDomInfo == null)
  1053. {
  1054. contractCodeDomInfo = new ContractCodeDomInfo();
  1055. dataContractSet.SetContractCodeDomInfo(keyValueContract, contractCodeDomInfo);
  1056. ExportClassDataContract(keyValueContract, contractCodeDomInfo);
  1057. contractCodeDomInfo.IsProcessed = true;
  1058. }
  1059. }
  1060. }
  1061. void ExportCollectionDataContract(CollectionDataContract collectionContract, ContractCodeDomInfo contractCodeDomInfo)
  1062. {
  1063. GenerateType(collectionContract, contractCodeDomInfo);
  1064. if (contractCodeDomInfo.ReferencedTypeExists)
  1065. return;
  1066. string dataContractName = GetNameForAttribute(collectionContract.StableName.Name);
  1067. // If type name is not expected, generate collection type that derives from referenced list type and uses [CollectionDataContract]
  1068. if (!SupportsGenericTypeReference)
  1069. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  1070. SR.GetString(SR.CannotUseGenericTypeAsBase, dataContractName,
  1071. collectionContract.StableName.Namespace)));
  1072. DataContract itemContract = collectionContract.ItemContract;
  1073. bool isItemTypeNullable = collectionContract.IsItemTypeNullable;
  1074. CodeTypeReference baseTypeReference;
  1075. bool foundDictionaryBase = TryGetReferencedDictionaryType(collectionContract, out baseTypeReference);
  1076. if (!foundDictionaryBase)
  1077. {
  1078. if (collectionContract.IsDictionary)
  1079. {
  1080. GenerateKeyValueType(collectionContract.ItemContract as ClassDataContract);
  1081. }
  1082. if (!TryGetReferencedListType(itemContract, isItemTypeNullable, out baseTypeReference))
  1083. {
  1084. if (SupportsGenericTypeReference)
  1085. {
  1086. baseTypeReference = GetCodeTypeReference(Globals.TypeOfListGeneric);
  1087. baseTypeReference.TypeArguments.Add(GetElementTypeReference(itemContract, isItemTypeNullable));
  1088. }
  1089. else
  1090. {
  1091. string expectedTypeName = Globals.ArrayPrefix + itemContract.StableName.Name;
  1092. string expectedTypeNs = DataContract.GetCollectionNamespace(itemContract.StableName.Namespace);
  1093. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedBaseTypeDoesNotExist,
  1094. dataContractName, collectionContract.StableName.Namespace,
  1095. expectedTypeName, expectedTypeNs, DataContract.GetClrTypeFullName(Globals.TypeOfIListGeneric), DataContract.GetClrTypeFullName(Globals.TypeOfICollectionGeneric))));
  1096. }
  1097. }
  1098. }
  1099. CodeTypeDeclaration generatedType = contractCodeDomInfo.TypeDeclaration;
  1100. generatedType.BaseTypes.Add(baseTypeReference);
  1101. CodeAttributeDeclaration collectionContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfCollectionDataContractAttribute));
  1102. collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName)));
  1103. collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(collectionContract.StableName.Namespace)));
  1104. if (collectionContract.IsReference != Globals.DefaultIsReference)
  1105. collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsReferenceProperty, new CodePrimitiveExpression(collectionContract.IsReference)));
  1106. collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ItemNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.ItemName))));
  1107. if (foundDictionaryBase)
  1108. {
  1109. collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.KeyNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.KeyName))));
  1110. collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ValueNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.ValueName))));
  1111. }
  1112. generatedType.CustomAttributes.Add(collectionContractAttribute);
  1113. AddImportStatement(Globals.TypeOfCollectionDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace);
  1114. AddSerializableAttribute(GenerateSerializableTypes, generatedType, contractCodeDomInfo);
  1115. }
  1116. private void ExportXmlDataContract(XmlDataContract xmlDataContract, ContractCodeDomInfo contractCodeDomInfo)
  1117. {
  1118. GenerateType(xmlDataContract, contractCodeDomInfo);
  1119. if (contractCodeDomInfo.ReferencedTypeExists)
  1120. return;
  1121. CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration;
  1122. if (SupportsPartialTypes)
  1123. type.IsPartial = true;
  1124. if (xmlDataContract.IsValueType)
  1125. type.IsStruct = true;
  1126. else
  1127. {
  1128. type.IsClass = true;
  1129. type.BaseTypes.Add(Globals.TypeOfObject);
  1130. }
  1131. AddSerializableAttribute(GenerateSerializableTypes, type, contractCodeDomInfo);
  1132. type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfIXmlSerializable));
  1133. type.Members.Add(NodeArrayField);
  1134. type.Members.Add(NodeArrayProperty);
  1135. type.Members.Add(ReadXmlMethod);
  1136. type.Members.Add(WriteXmlMethod);
  1137. type.Members.Add(GetSchemaMethod);
  1138. if (xmlDataContract.IsAnonymous && !xmlDataContract.HasRoot)
  1139. {
  1140. type.CustomAttributes.Add(new CodeAttributeDeclaration(
  1141. DataContract.GetClrTypeFullName(Globals.TypeOfXmlSchemaProviderAttribute),
  1142. new CodeAttributeArgument(NullReference),
  1143. new CodeAttributeArgument(Globals.IsAnyProperty, new CodePrimitiveExpression(true)))
  1144. );
  1145. }
  1146. else
  1147. {
  1148. type.CustomAttributes.Add(new CodeAttributeDeclaration(
  1149. DataContract.GetClrTypeFullName(Globals.TypeOfXmlSchemaProviderAttribute),
  1150. new CodeAttributeArgument(new CodePrimitiveExpression(Globals.ExportSchemaMethod)))
  1151. );
  1152. CodeMemberField typeNameField = new CodeMemberField(Globals.TypeOfXmlQualifiedName, typeNameFieldName);
  1153. typeNameField.Attributes |= MemberAttributes.Static | MemberAttributes.Private;
  1154. XmlQualifiedName typeName = xmlDataContract.IsAnonymous
  1155. ? SchemaImporter.ImportActualType(xmlDataContract.XsdType.Annotation, xmlDataContract.StableName, xmlDataContract.StableName)
  1156. : xmlDataContract.StableName;
  1157. typeNameField.InitExpression = new CodeObjectCreateExpression(Globals.TypeOfXmlQualifiedName, new CodePrimitiveExpression(typeName.Name), new CodePrimitiveExpression(typeName.Namespace));
  1158. type.Members.Add(typeNameField);
  1159. type.Members.Add(GetSchemaStaticMethod);
  1160. bool isElementNameDifferent =
  1161. (xmlDataContract.TopLevelElementName != null && xmlDataContract.TopLevelElementName.Value != xmlDataContract.StableName.Name) ||
  1162. (xmlDataContract.TopLevelElementNamespace != null && xmlDataContract.TopLevelElementNamespace.Value != xmlDataContract.StableName.Namespace);
  1163. if (isElementNameDifferent || xmlDataContract.IsTopLevelElementNullable == false)
  1164. {
  1165. CodeAttributeDeclaration xmlRootAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfXmlRootAttribute));
  1166. if (isElementNameDifferent)
  1167. {
  1168. if (xmlDataContract.TopLevelElementName != null)
  1169. {
  1170. xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("ElementName", new CodePrimitiveExpression(xmlDataContract.TopLevelElementName.Value)));
  1171. }
  1172. if (xmlDataContract.TopLevelElementNamespace != null)
  1173. {
  1174. xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(xmlDataContract.TopLevelElementNamespace.Value)));
  1175. }
  1176. }
  1177. if (xmlDataContract.IsTopLevelElementNullable == false)
  1178. xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("IsNullable", new CodePrimitiveExpression(false)));
  1179. type.CustomAttributes.Add(xmlRootAttribute);
  1180. }
  1181. }
  1182. AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct);
  1183. }
  1184. CodeNamespace GetCodeNamespace(string clrNamespace, string dataContractNamespace, ContractCodeDomInfo contractCodeDomInfo)
  1185. {
  1186. if (contractCodeDomInfo.CodeNamespace != null)
  1187. return contractCodeDomInfo.CodeNamespace;
  1188. CodeNamespaceCollection codeNamespaceCollection = codeCompileUnit.Namespaces;
  1189. foreach (CodeNamespace ns in codeNamespaceCollection)
  1190. {
  1191. if (ns.Name == clrNamespace)
  1192. {
  1193. contractCodeDomInfo.CodeNamespace = ns;
  1194. return ns;
  1195. }
  1196. }
  1197. CodeNamespace codeNamespace = new CodeNamespace(clrNamespace);
  1198. codeNamespaceCollection.Add(codeNamespace);
  1199. if (CanDeclareAssemblyAttribute(contractCodeDomInfo)
  1200. && NeedsExplicitNamespace(dataContractNamespace, clrNamespace))
  1201. {
  1202. CodeAttributeDeclaration namespaceAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfContractNamespaceAttribute));
  1203. namespaceAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(dataContractNamespace)));
  1204. namespaceAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ClrNamespaceProperty, new CodePrimitiveExpression(clrNamespace)));
  1205. codeCompileUnit.AssemblyCustomAttributes.Add(namespaceAttribute);
  1206. }
  1207. contractCodeDomInfo.CodeNamespace = codeNamespace;
  1208. return codeNamespace;
  1209. }
  1210. string GetMemberName(string memberName, ContractCodeDomInfo contractCodeDomInfo)
  1211. {
  1212. memberName = GetClrIdentifier(memberName, Globals.DefaultGeneratedMember);
  1213. if (memberName == contractCodeDomInfo.TypeDeclaration.Name)
  1214. memberName = AppendToValidClrIdentifier(memberName, Globals.DefaultMemberSuffix);
  1215. if (contractCodeDomInfo.GetMemberNames().ContainsKey(memberName))
  1216. {
  1217. string uniqueMemberName = null;
  1218. for (int i = 1;; i++)
  1219. {
  1220. uniqueMemberName = AppendToValidClrIdentifier(memberName, i.ToString(NumberFormatInfo.InvariantInfo));
  1221. if (!contractCodeDomInfo.GetMemberNames().ContainsKey(uniqueMemberName))
  1222. {
  1223. memberName = uniqueMemberName;
  1224. break;
  1225. }
  1226. }
  1227. }
  1228. contractCodeDomInfo.GetMemberNames().Add(memberName, null);
  1229. return memberName;
  1230. }
  1231. void AddBaseMemberNames(ContractCodeDomInfo baseContractCodeDomInfo, ContractCodeDomInfo contractCodeDomInfo)
  1232. {
  1233. if (!baseContractCodeDomInfo.ReferencedTypeExists)
  1234. {
  1235. Dictionary<string, object> baseMemberNames = baseContractCodeDomInfo.GetMemberNames();
  1236. Dictionary<string, object> memberNames = contractCodeDomInfo.GetMemberNames();
  1237. foreach (KeyValuePair<string, object> pair in baseMemberNames)
  1238. {
  1239. memberNames.Add(pair.Key, pair.Value);
  1240. }
  1241. }
  1242. }
  1243. [Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeGenerator.IsValidLanguageIndependentIdentifier(..) method that has a LinkDemand.",
  1244. Safe = "Safe because it doesn't leak security sensitive information.")]
  1245. [SecuritySafeCritical]
  1246. static string GetClrIdentifier(string identifier, string defaultIdentifier)
  1247. {
  1248. if (identifier.Length <= MaxIdentifierLength && System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(identifier))
  1249. return identifier;
  1250. bool isStart = true;
  1251. StringBuilder builder = new StringBuilder();
  1252. for (int i = 0; i < identifier.Length && builder.Length < MaxIdentifierLength; i++)
  1253. {
  1254. char c = identifier[i];
  1255. if (IsValid(c))
  1256. {
  1257. if (isStart && !IsValidStart(c))
  1258. builder.Append("_");
  1259. builder.Append(c);
  1260. isStart = false;
  1261. }
  1262. }
  1263. if (builder.Length == 0)
  1264. return defaultIdentifier;
  1265. return builder.ToString();
  1266. }
  1267. static string AppendToValidClrIdentifier(string identifier, string appendString)
  1268. {
  1269. int availableLength = MaxIdentifierLength - identifier.Length;
  1270. int requiredLength = appendString.Length;
  1271. if (availableLength < requiredLength)
  1272. identifier = identifier.Substring(0, MaxIdentifierLength - requiredLength);
  1273. identifier += appendString;
  1274. return identifier;
  1275. }
  1276. string GetClrNamespace(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo)
  1277. {
  1278. string clrNamespace = contractCodeDomInfo.ClrNamespace;
  1279. bool usesWildcardNamespace = false;
  1280. if (clrNamespace == null)
  1281. {
  1282. if (!Namespaces.TryGetValue(dataContract.StableName.Namespace, out clrNamespace))
  1283. {
  1284. if (Namespaces.TryGetValue(wildcardNamespaceMapping, out clrNamespace))
  1285. {
  1286. usesWildcardNamespace = true;
  1287. }
  1288. else
  1289. {
  1290. clrNamespace = GetClrNamespace(dataContract.StableName.Namespace);
  1291. if (ClrNamespaces.ContainsKey(clrNamespace))
  1292. {
  1293. string uniqueNamespace = null;
  1294. for (int i = 1;; i++)
  1295. {
  1296. uniqueNamespace = ((clrNamespace.Length == 0) ? Globals.DefaultClrNamespace : clrNamespace) + i.ToString(NumberFormatInfo.InvariantInfo);
  1297. if (!ClrNamespaces.ContainsKey(uniqueNamespace))
  1298. {
  1299. clrNamespace = uniqueNamespace;
  1300. break;
  1301. }
  1302. }
  1303. }
  1304. AddNamespacePair(dataContract.StableName.Namespace, clrNamespace);
  1305. }
  1306. }
  1307. contractCodeDomInfo.ClrNamespace = clrNamespace;
  1308. contractCodeDomInfo.UsesWildcardNamespace = usesWildcardNamespace;
  1309. }
  1310. return clrNamespace;
  1311. }
  1312. void AddNamespacePair(string dataContractNamespace, string clrNamespace)
  1313. {
  1314. Namespaces.Add(dataContractNamespace, clrNamespace);
  1315. ClrNamespaces.Add(clrNamespace, dataContractNamespace);
  1316. }
  1317. void AddImportStatement(string clrNamespace, CodeNamespace codeNamespace)
  1318. {
  1319. if (clrNamespace == codeNamespace.Name)
  1320. return;
  1321. CodeNamespaceImportCollection importCollection = codeNamespace.Imports;
  1322. foreach (CodeNamespaceImport import in importCollection)
  1323. {
  1324. if (import.Namespace == clrNamespace)
  1325. return;
  1326. }
  1327. importCollection.Add(new CodeNamespaceImport(clrNamespace));
  1328. }
  1329. static string GetClrNamespace(string dataContractNamespace)
  1330. {
  1331. if (dataContractNamespace == null || dataContractNamespace.Length == 0)
  1332. return String.Empty;
  1333. Uri uri = null;
  1334. StringBuilder builder = new StringBuilder();
  1335. if (Uri.TryCreate(dataContractNamespace, UriKind.RelativeOrAbsolute, out uri))
  1336. {
  1337. Dictionary<string, object> fragments = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
  1338. if (!uri.IsAbsoluteUri)
  1339. AddToNamespace(builder, uri.OriginalString, fragments);
  1340. else
  1341. {
  1342. string uriString = uri.AbsoluteUri;
  1343. if (uriString.StartsWith(Globals.DataContractXsdBaseNamespace, StringComparison.Ordinal))
  1344. AddToNamespace(builder, uriString.Substring(Globals.DataContractXsdBaseNamespace.Length), fragments);
  1345. else
  1346. {
  1347. string host = uri.Host;
  1348. if (host != null)
  1349. AddToNamespace(builder, host, fragments);
  1350. string path = uri.PathAndQuery;
  1351. if (path != null)
  1352. AddToNamespace(builder, path, fragments);
  1353. }
  1354. }
  1355. }
  1356. if (builder.Length == 0)
  1357. return String.Empty;
  1358. int length = builder.Length;
  1359. if (builder[builder.Length - 1] == '.')
  1360. length--;
  1361. length = Math.Min(MaxIdentifierLength, length);
  1362. return builder.ToString(0, length);
  1363. }
  1364. static void AddToNamespace(StringBuilder builder, string fragment, Dictionary<string, object> fragments)
  1365. {
  1366. if (fragment == null)
  1367. return;
  1368. bool isStart = true;
  1369. int fragmentOffset = builder.Length;
  1370. int fragmentLength = 0;
  1371. for (int i = 0; i < fragment.Length && builder.Length < MaxIdentifierLength; i++)
  1372. {
  1373. char c = fragment[i];
  1374. if (IsValid(c))
  1375. {
  1376. if (isStart && !IsValidStart(c))
  1377. builder.Append("_");
  1378. builder.Append(c);
  1379. fragmentLength++;
  1380. isStart = false;
  1381. }
  1382. else if ((c == '.' || c == '/' || c == ':') && (builder.Length == 1
  1383. || (builder.Length > 1 && builder[builder.Length - 1] != '.')))
  1384. {
  1385. AddNamespaceFragment(builder, fragmentOffset, fragmentLength, fragments);
  1386. builder.Append('.');
  1387. fragmentOffset = builder.Length;
  1388. fragmentLength = 0;
  1389. isStart = true;
  1390. }
  1391. }
  1392. AddNamespaceFragment(builder, fragmentOffset, fragmentLength, fragments);
  1393. }
  1394. static void AddNamespaceFragment(StringBuilder builder, int fragmentOffset,
  1395. int fragmentLength, Dictionary<string, object> fragments)
  1396. {
  1397. if (fragmentLength == 0)
  1398. return;
  1399. string nsFragment = builder.ToString(fragmentOffset, fragmentLength);
  1400. if (fragments.ContainsKey(nsFragment))
  1401. {
  1402. for (int i = 1;; i++)
  1403. {
  1404. string uniquifier = i.ToString(NumberFormatInfo.InvariantInfo);
  1405. string uniqueNsFragment = AppendToValidClrIdentifier(nsFragment, uniquifier);
  1406. if (!fragments.ContainsKey(uniqueNsFragment))
  1407. {
  1408. builder.Append(uniquifier);
  1409. nsFragment = uniqueNsFragment;
  1410. break;
  1411. }
  1412. if (i == Int32.MaxValue)
  1413. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CannotComputeUniqueName, nsFragment)));
  1414. }
  1415. }
  1416. fragments.Add(nsFragment, null);
  1417. }
  1418. static bool IsValidStart(char c)
  1419. {
  1420. return (Char.GetUnicodeCategory(c) != UnicodeCategory.DecimalDigitNumber);
  1421. }
  1422. static bool IsValid(char c)
  1423. {
  1424. UnicodeCategory uc = Char.GetUnicodeCategory(c);
  1425. // each char must be Lu, Ll, Lt, Lm, Lo, Nd, Mn, Mc, Pc
  1426. switch (uc)
  1427. {
  1428. case UnicodeCategory.UppercaseLetter: // Lu
  1429. case UnicodeCategory.LowercaseLetter: // Ll
  1430. case UnicodeCategory.TitlecaseLetter: // Lt
  1431. case UnicodeCategory.ModifierLetter: // Lm
  1432. case UnicodeCategory.OtherLetter: // Lo
  1433. case UnicodeCategory.DecimalDigitNumber: // Nd
  1434. case UnicodeCategory.NonSpacingMark: // Mn
  1435. case UnicodeCategory.SpacingCombiningMark: // Mc
  1436. case UnicodeCategory.ConnectorPunctuation: // Pc
  1437. return true;
  1438. default:
  1439. return false;
  1440. }
  1441. }
  1442. CodeTypeReference CodeTypeIPropertyChange
  1443. {
  1444. get { return GetCodeTypeReference(typeof(System.ComponentModel.INotifyPropertyChanged)); }
  1445. }
  1446. CodeThisReferenceExpression ThisReference
  1447. {
  1448. get { return new CodeThisReferenceExpression(); }
  1449. }
  1450. CodePrimitiveExpression NullReference
  1451. {
  1452. get { return new CodePrimitiveExpression(null); }
  1453. }
  1454. CodeParameterDeclarationExpression SerializationInfoParameter
  1455. {
  1456. get { return new CodeParameterDeclarationExpression(GetCodeTypeReference(Globals.TypeOfSerializationInfo), Globals.SerializationInfoFieldName); }
  1457. }
  1458. CodeParameterDeclarationExpression StreamingContextParameter
  1459. {
  1460. get { return new CodeParameterDeclarationExpression(GetCodeTypeReference(Globals.TypeOfStreamingContext), Globals.ContextFieldName); }
  1461. }
  1462. CodeAttributeDeclaration SerializableAttribute
  1463. {
  1464. get { return new CodeAttributeDeclaration(GetCodeTypeReference(Globals.TypeOfSerializableAttribute)); }
  1465. }
  1466. CodeMemberProperty NodeArrayProperty
  1467. {
  1468. get
  1469. {
  1470. return CreateProperty(GetCodeTypeReference(Globals.TypeOfXmlNodeArray), Globals.NodeArrayPropertyName, Globals.NodeArrayFieldName, false/*isValueType*/);
  1471. }
  1472. }
  1473. CodeMemberField NodeArrayField
  1474. {
  1475. get
  1476. {
  1477. CodeMemberField nodeArrayField = new CodeMemberField();
  1478. nodeArrayField.Type = GetCodeTypeReference(Globals.TypeOfXmlNodeArray);
  1479. nodeArrayField.Name = Globals.NodeArrayFieldName;
  1480. nodeArrayField.Attributes = MemberAttributes.Private;
  1481. return nodeArrayField;
  1482. }
  1483. }
  1484. CodeMemberMethod ReadXmlMethod
  1485. {
  1486. get
  1487. {
  1488. CodeMemberMethod readXmlMethod = new CodeMemberMethod();
  1489. readXmlMethod.Name = "ReadXml";
  1490. CodeParameterDeclarationExpression readerArg = new CodeParameterDeclarationExpression(typeof(XmlReader), "reader");
  1491. readXmlMethod.Parameters.Add(readerArg);
  1492. readXmlMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  1493. readXmlMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable);
  1494. CodeAssignStatement setNode = new CodeAssignStatement();
  1495. setNode.Left = new CodeFieldReferenceExpression(ThisReference, Globals.NodeArrayFieldName);
  1496. setNode.Right = new CodeMethodInvokeExpression(
  1497. new CodeTypeReferenceExpression(GetCodeTypeReference(Globals.TypeOfXmlSerializableServices)),
  1498. XmlSerializableServices.ReadNodesMethodName,
  1499. new CodeArgumentReferenceExpression(readerArg.Name)
  1500. );
  1501. readXmlMethod.Statements.Add(setNode);
  1502. return readXmlMethod;
  1503. }
  1504. }
  1505. CodeMemberMethod WriteXmlMethod
  1506. {
  1507. get
  1508. {
  1509. CodeMemberMethod writeXmlMethod = new CodeMemberMethod();
  1510. writeXmlMethod.Name = "WriteXml";
  1511. CodeParameterDeclarationExpression writerArg = new CodeParameterDeclarationExpression(typeof(XmlWriter), "writer");
  1512. writeXmlMethod.Parameters.Add(writerArg);
  1513. writeXmlMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  1514. writeXmlMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable);
  1515. writeXmlMethod.Statements.Add(
  1516. new CodeMethodInvokeExpression(
  1517. new CodeTypeReferenceExpression(GetCodeTypeReference(Globals.TypeOfXmlSerializableServices)),
  1518. XmlSerializableServices.WriteNodesMethodName,
  1519. new CodeArgumentReferenceExpression(writerArg.Name),
  1520. new CodePropertyReferenceExpression(ThisReference, Globals.NodeArrayPropertyName)
  1521. )
  1522. );
  1523. return writeXmlMethod;
  1524. }
  1525. }
  1526. CodeMemberMethod GetSchemaMethod
  1527. {
  1528. get
  1529. {
  1530. CodeMemberMethod getSchemaMethod = new CodeMemberMethod();
  1531. getSchemaMethod.Name = "GetSchema";
  1532. getSchemaMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  1533. getSchemaMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable);
  1534. getSchemaMethod.ReturnType = GetCodeTypeReference(typeof(XmlSchema));
  1535. getSchemaMethod.Statements.Add(new CodeMethodReturnStatement(NullReference));
  1536. return getSchemaMethod;
  1537. }
  1538. }
  1539. CodeMemberMethod GetSchemaStaticMethod
  1540. {
  1541. get
  1542. {
  1543. CodeMemberMethod getSchemaStaticMethod = new CodeMemberMethod();
  1544. getSchemaStaticMethod.Name = Globals.ExportSchemaMethod;
  1545. getSchemaStaticMethod.ReturnType = GetCodeTypeReference(Globals.TypeOfXmlQualifiedName);
  1546. CodeParameterDeclarationExpression paramDeclaration = new CodeParameterDeclarationExpression(Globals.TypeOfXmlSchemaSet, "schemas");
  1547. getSchemaStaticMethod.Parameters.Add(paramDeclaration);
  1548. getSchemaStaticMethod.Attributes = MemberAttributes.Static | MemberAttributes.Public;
  1549. getSchemaStaticMethod.Statements.Add(
  1550. new CodeMethodInvokeExpression(
  1551. new CodeTypeReferenceExpression(GetCodeTypeReference(typeof(XmlSerializableServices))),
  1552. XmlSerializableServices.AddDefaultSchemaMethodName,
  1553. new CodeArgumentReferenceExpression(paramDeclaration.Name),
  1554. new CodeFieldReferenceExpression(null, typeNameFieldName)
  1555. )
  1556. );
  1557. getSchemaStaticMethod.Statements.Add(
  1558. new CodeMethodReturnStatement(
  1559. new CodeFieldReferenceExpression(null, typeNameFieldName)
  1560. )
  1561. );
  1562. return getSchemaStaticMethod;
  1563. }
  1564. }
  1565. CodeConstructor ISerializableBaseConstructor
  1566. {
  1567. get
  1568. {
  1569. CodeConstructor baseConstructor = new CodeConstructor();
  1570. baseConstructor.Attributes = MemberAttributes.Public;
  1571. baseConstructor.Parameters.Add(SerializationInfoParameter);
  1572. baseConstructor.Parameters.Add(StreamingContextParameter);
  1573. CodeAssignStatement setObjectData = new CodeAssignStatement();
  1574. setObjectData.Left = new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoFieldName);
  1575. setObjectData.Right = new CodeArgumentReferenceExpression(Globals.SerializationInfoFieldName);
  1576. baseConstructor.Statements.Add(setObjectData);
  1577. // Special-cased check for vb here since CodeGeneratorOptions does not provide information indicating that VB cannot initialize event member
  1578. if (EnableDataBinding && SupportsDeclareEvents && String.CompareOrdinal(FileExtension, "vb") != 0)
  1579. {
  1580. baseConstructor.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(ThisReference, PropertyChangedEvent.Name), NullReference));
  1581. }
  1582. return baseConstructor;
  1583. }
  1584. }
  1585. CodeConstructor ISerializableDerivedConstructor
  1586. {
  1587. get
  1588. {
  1589. CodeConstructor derivedConstructor = new CodeConstructor();
  1590. derivedConstructor.Attributes = MemberAttributes.Public;
  1591. derivedConstructor.Parameters.Add(SerializationInfoParameter);
  1592. derivedConstructor.Parameters.Add(StreamingContextParameter);
  1593. derivedConstructor.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(Globals.SerializationInfoFieldName));
  1594. derivedConstructor.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(Globals.ContextFieldName));
  1595. return derivedConstructor;
  1596. }
  1597. }
  1598. CodeMemberField SerializationInfoField
  1599. {
  1600. get
  1601. {
  1602. CodeMemberField serializationInfoField = new CodeMemberField();
  1603. serializationInfoField.Type = GetCodeTypeReference(Globals.TypeOfSerializationInfo);
  1604. serializationInfoField.Name = Globals.SerializationInfoFieldName;
  1605. serializationInfoField.Attributes = MemberAttributes.Private;
  1606. return serializationInfoField;
  1607. }
  1608. }
  1609. CodeMemberProperty SerializationInfoProperty
  1610. {
  1611. get
  1612. {
  1613. return CreateProperty(GetCodeTypeReference(Globals.TypeOfSerializationInfo), Globals.SerializationInfoPropertyName, Globals.SerializationInfoFieldName, false/*isValueType*/);
  1614. }
  1615. }
  1616. CodeMemberMethod GetObjectDataMethod
  1617. {
  1618. get
  1619. {
  1620. CodeMemberMethod getObjectDataMethod = new CodeMemberMethod();
  1621. getObjectDataMethod.Name = Globals.GetObjectDataMethodName;
  1622. getObjectDataMethod.Parameters.Add(SerializationInfoParameter);
  1623. getObjectDataMethod.Parameters.Add(StreamingContextParameter);
  1624. getObjectDataMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  1625. getObjectDataMethod.ImplementationTypes.Add(Globals.TypeOfISerializable);
  1626. // Generates: if (this.SerializationInfo == null) return;
  1627. CodeConditionStatement returnIfNull = new CodeConditionStatement();
  1628. returnIfNull.Condition = new CodeBinaryOperatorExpression(
  1629. new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoPropertyName),
  1630. CodeBinaryOperatorType.IdentityEquality,
  1631. NullReference);
  1632. returnIfNull.TrueStatements.Add(new CodeMethodReturnStatement());
  1633. // Generates: SerializationInfoEnumerator enumerator = this.SerializationInfo.GetEnumerator();
  1634. CodeVariableDeclarationStatement getEnumerator = new CodeVariableDeclarationStatement();
  1635. getEnumerator.Type = GetCodeTypeReference(Globals.TypeOfSerializationInfoEnumerator);
  1636. getEnumerator.Name = Globals.EnumeratorFieldName;
  1637. getEnumerator.InitExpression = new CodeMethodInvokeExpression(
  1638. new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoPropertyName),
  1639. Globals.GetEnumeratorMethodName);
  1640. //Generates: SerializationEntry entry = enumerator.Current;
  1641. CodeVariableDeclarationStatement getCurrent = new CodeVariableDeclarationStatement();
  1642. getCurrent.Type = GetCodeTypeReference(Globals.TypeOfSerializationEntry);
  1643. getCurrent.Name = Globals.SerializationEntryFieldName;
  1644. getCurrent.InitExpression = new CodePropertyReferenceExpression(
  1645. new CodeVariableReferenceExpression(Globals.EnumeratorFieldName),
  1646. Globals.CurrentPropertyName);
  1647. //Generates: info.AddValue(entry.Name, entry.Value);
  1648. CodeExpressionStatement addValue = new CodeExpressionStatement();
  1649. CodePropertyReferenceExpression getCurrentName = new CodePropertyReferenceExpression(
  1650. new CodeVariableReferenceExpression(Globals.SerializationEntryFieldName),
  1651. Globals.NameProperty);
  1652. CodePropertyReferenceExpression getCurrentValue = new CodePropertyReferenceExpression(
  1653. new CodeVariableReferenceExpression(Globals.SerializationEntryFieldName),
  1654. Globals.ValueProperty);
  1655. addValue.Expression = new CodeMethodInvokeExpression(
  1656. new CodeArgumentReferenceExpression(Globals.SerializationInfoFieldName),
  1657. Globals.AddValueMethodName,
  1658. new CodeExpression[] { getCurrentName, getCurrentValue });
  1659. //Generates: for (; enumerator.MoveNext(); )
  1660. CodeIterationStatement loop = new CodeIterationStatement();
  1661. loop.TestExpression = new CodeMethodInvokeExpression(
  1662. new CodeVariableReferenceExpression(Globals.EnumeratorFieldName),
  1663. Globals.MoveNextMethodName);
  1664. loop.InitStatement = loop.IncrementStatement = new CodeSnippetStatement(String.Empty);
  1665. loop.Statements.Add(getCurrent);
  1666. loop.Statements.Add(addValue);
  1667. getObjectDataMethod.Statements.Add(returnIfNull);
  1668. getObjectDataMethod.Statements.Add(getEnumerator);
  1669. getObjectDataMethod.Statements.Add(loop);
  1670. return getObjectDataMethod;
  1671. }
  1672. }
  1673. CodeMemberField ExtensionDataObjectField
  1674. {
  1675. get
  1676. {
  1677. CodeMemberField extensionDataObjectField = new CodeMemberField();
  1678. extensionDataObjectField.Type = GetCodeTypeReference(Globals.TypeOfExtensionDataObject);
  1679. extensionDataObjectField.Name = Globals.ExtensionDataObjectFieldName;
  1680. extensionDataObjectField.Attributes = MemberAttributes.Private;
  1681. return extensionDataObjectField;
  1682. }
  1683. }
  1684. CodeMemberProperty ExtensionDataObjectProperty
  1685. {
  1686. get
  1687. {
  1688. CodeMemberProperty extensionDataObjectProperty = new CodeMemberProperty();
  1689. extensionDataObjectProperty.Type = GetCodeTypeReference(Globals.TypeOfExtensionDataObject);
  1690. extensionDataObjectProperty.Name = Globals.ExtensionDataObjectPropertyName;
  1691. extensionDataObjectProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  1692. extensionDataObjectProperty.ImplementationTypes.Add(Globals.TypeOfIExtensibleDataObject);
  1693. CodeMethodReturnStatement propertyGet = new CodeMethodReturnStatement();
  1694. propertyGet.Expression = new CodeFieldReferenceExpression(ThisReference, Globals.ExtensionDataObjectFieldName);
  1695. extensionDataObjectProperty.GetStatements.Add(propertyGet);
  1696. CodeAssignStatement propertySet = new CodeAssignStatement();
  1697. propertySet.Left = new CodeFieldReferenceExpression(ThisReference, Globals.ExtensionDataObjectFieldName);
  1698. propertySet.Right = new CodePropertySetValueReferenceExpression();
  1699. extensionDataObjectProperty.SetStatements.Add(propertySet);
  1700. return extensionDataObjectProperty;
  1701. }
  1702. }
  1703. CodeMemberMethod RaisePropertyChangedEventMethod
  1704. {
  1705. get
  1706. {
  1707. CodeMemberMethod raisePropertyChangedEventMethod = new CodeMemberMethod();
  1708. raisePropertyChangedEventMethod.Name = "RaisePropertyChanged";
  1709. raisePropertyChangedEventMethod.Attributes = MemberAttributes.Final;
  1710. CodeArgumentReferenceExpression propertyName = new CodeArgumentReferenceExpression("propertyName");
  1711. raisePropertyChangedEventMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), propertyName.ParameterName));
  1712. CodeVariableReferenceExpression propertyChanged = new CodeVariableReferenceExpression("propertyChanged");
  1713. raisePropertyChangedEventMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(PropertyChangedEventHandler), propertyChanged.VariableName, new CodeEventReferenceExpression(ThisReference, PropertyChangedEvent.Name)));
  1714. CodeConditionStatement ifStatement = new CodeConditionStatement(new CodeBinaryOperatorExpression(propertyChanged, CodeBinaryOperatorType.IdentityInequality, NullReference));
  1715. raisePropertyChangedEventMethod.Statements.Add(ifStatement);
  1716. ifStatement.TrueStatements.Add(new CodeDelegateInvokeExpression(propertyChanged, ThisReference, new CodeObjectCreateExpression(typeof(PropertyChangedEventArgs), propertyName)));
  1717. return raisePropertyChangedEventMethod;
  1718. }
  1719. }
  1720. CodeMemberEvent PropertyChangedEvent
  1721. {
  1722. get
  1723. {
  1724. CodeMemberEvent propertyChangedEvent = new CodeMemberEvent();
  1725. propertyChangedEvent.Attributes = MemberAttributes.Public;
  1726. propertyChangedEvent.Name = "PropertyChanged";
  1727. propertyChangedEvent.Type = GetCodeTypeReference(typeof(PropertyChangedEventHandler));
  1728. propertyChangedEvent.ImplementationTypes.Add(Globals.TypeOfIPropertyChange);
  1729. return propertyChangedEvent;
  1730. }
  1731. }
  1732. CodeMemberProperty CreateProperty(CodeTypeReference type, string propertyName, string fieldName, bool isValueType)
  1733. {
  1734. return CreateProperty(type, propertyName, fieldName, isValueType, EnableDataBinding && SupportsDeclareEvents);
  1735. }
  1736. CodeMemberProperty CreateProperty(CodeTypeReference type, string propertyName, string fieldName, bool isValueType, bool raisePropertyChanged)
  1737. {
  1738. CodeMemberProperty property = new CodeMemberProperty();
  1739. property.Type = type;
  1740. property.Name = propertyName;
  1741. property.Attributes = MemberAttributes.Final;
  1742. if (GenerateInternalTypes)
  1743. property.Attributes |= MemberAttributes.Assembly;
  1744. else
  1745. property.Attributes |= MemberAttributes.Public;
  1746. CodeMethodReturnStatement propertyGet = new CodeMethodReturnStatement();
  1747. propertyGet.Expression = new CodeFieldReferenceExpression(ThisReference, fieldName);
  1748. property.GetStatements.Add(propertyGet);
  1749. CodeAssignStatement propertySet = new CodeAssignStatement();
  1750. propertySet.Left = new CodeFieldReferenceExpression(ThisReference, fieldName);
  1751. propertySet.Right = new CodePropertySetValueReferenceExpression();
  1752. if (raisePropertyChanged)
  1753. {
  1754. CodeConditionStatement ifStatement = new CodeConditionStatement();
  1755. CodeExpression left = new CodeFieldReferenceExpression(ThisReference, fieldName);
  1756. CodeExpression right = new CodePropertySetValueReferenceExpression();
  1757. if (!isValueType)
  1758. {
  1759. left = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(Globals.TypeOfObject),
  1760. "ReferenceEquals", new CodeExpression[] { left, right });
  1761. }
  1762. else
  1763. {
  1764. left = new CodeMethodInvokeExpression(left, "Equals", new CodeExpression[] { right });
  1765. }
  1766. right = new CodePrimitiveExpression(true);
  1767. ifStatement.Condition = new CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.IdentityInequality, right);
  1768. ifStatement.TrueStatements.Add(propertySet);
  1769. ifStatement.TrueStatements.Add(new CodeMethodInvokeExpression(ThisReference, RaisePropertyChangedEventMethod.Name, new CodePrimitiveExpression(propertyName)));
  1770. property.SetStatements.Add(ifStatement);
  1771. }
  1772. else
  1773. property.SetStatements.Add(propertySet);
  1774. return property;
  1775. }
  1776. }
  1777. }