XmlSerializationWriter.cs 180 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904
  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSerializationWriter.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">Microsoft</owner>
  6. //------------------------------------------------------------------------------
  7. namespace System.Xml.Serialization {
  8. using System;
  9. using System.IO;
  10. using System.Collections;
  11. using System.Reflection;
  12. using System.Reflection.Emit;
  13. using System.Xml.Schema;
  14. using System.ComponentModel;
  15. using System.Diagnostics;
  16. using System.CodeDom.Compiler;
  17. using System.Globalization;
  18. using System.Text;
  19. using System.Threading;
  20. using System.Security.Permissions;
  21. using System.Runtime.Versioning;
  22. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter"]/*' />
  23. ///<internalonly/>
  24. public abstract class XmlSerializationWriter : XmlSerializationGeneratedCode {
  25. XmlWriter w;
  26. XmlSerializerNamespaces namespaces;
  27. int tempNamespacePrefix;
  28. Hashtable usedPrefixes;
  29. Hashtable references;
  30. string idBase;
  31. int nextId;
  32. Hashtable typeEntries;
  33. ArrayList referencesToWrite;
  34. Hashtable objectsInUse;
  35. string aliasBase = "q";
  36. bool soap12;
  37. bool escapeName = true;
  38. // this method must be called before any generated serialization methods are called
  39. internal void Init(XmlWriter w, XmlSerializerNamespaces namespaces, string encodingStyle, string idBase, TempAssembly tempAssembly) {
  40. this.w = w;
  41. this.namespaces = namespaces;
  42. this.soap12 = (encodingStyle == Soap12.Encoding);
  43. this.idBase = idBase;
  44. Init(tempAssembly);
  45. }
  46. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.EscapeName"]/*' />
  47. protected bool EscapeName {
  48. get {
  49. return escapeName;
  50. }
  51. set {
  52. escapeName = value;
  53. }
  54. }
  55. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.Writer"]/*' />
  56. protected XmlWriter Writer {
  57. get {
  58. return w;
  59. }
  60. set {
  61. w = value;
  62. }
  63. }
  64. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.Namespaces"]/*' />
  65. /// <devdoc>
  66. /// <para>[To be supplied.]</para>
  67. /// </devdoc>
  68. protected ArrayList Namespaces {
  69. get {
  70. return namespaces == null ? null : namespaces.NamespaceList;
  71. }
  72. set {
  73. if (value == null) {
  74. namespaces = null;
  75. }
  76. else {
  77. XmlQualifiedName[] qnames = (XmlQualifiedName[])value.ToArray(typeof(XmlQualifiedName));
  78. namespaces = new XmlSerializerNamespaces(qnames);
  79. }
  80. }
  81. }
  82. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromByteArrayBase64"]/*' />
  83. protected static byte[] FromByteArrayBase64(byte[] value) {
  84. // Unlike other "From" functions that one is just a place holder for automatic code generation.
  85. // The reason is performance and memory consumption for (potentially) big 64base-encoded chunks
  86. // And it is assumed that the caller generates the code that will distinguish between byte[] and string return types
  87. //
  88. return value;
  89. }
  90. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.ResolveDynamicAssembly"]/*' />
  91. ///<internalonly/>
  92. protected static Assembly ResolveDynamicAssembly(string assemblyFullName){
  93. return DynamicAssemblies.Get(assemblyFullName);
  94. }
  95. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromByteArrayHex"]/*' />
  96. protected static string FromByteArrayHex(byte[] value) {
  97. return XmlCustomFormatter.FromByteArrayHex(value);
  98. }
  99. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromDateTime"]/*' />
  100. protected static string FromDateTime(DateTime value) {
  101. return XmlCustomFormatter.FromDateTime(value);
  102. }
  103. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromDate"]/*' />
  104. protected static string FromDate(DateTime value) {
  105. return XmlCustomFormatter.FromDate(value);
  106. }
  107. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromTime"]/*' />
  108. protected static string FromTime(DateTime value) {
  109. return XmlCustomFormatter.FromTime(value);
  110. }
  111. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromChar"]/*' />
  112. protected static string FromChar(char value) {
  113. return XmlCustomFormatter.FromChar(value);
  114. }
  115. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromEnum"]/*' />
  116. protected static string FromEnum(long value, string[] values, long[] ids) {
  117. return XmlCustomFormatter.FromEnum(value, values, ids, null);
  118. }
  119. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromEnum1"]/*' />
  120. protected static string FromEnum(long value, string[] values, long[] ids, string typeName) {
  121. return XmlCustomFormatter.FromEnum(value, values, ids, typeName);
  122. }
  123. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlName"]/*' />
  124. protected static string FromXmlName(string name) {
  125. return XmlCustomFormatter.FromXmlName(name);
  126. }
  127. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlNCName"]/*' />
  128. protected static string FromXmlNCName(string ncName) {
  129. return XmlCustomFormatter.FromXmlNCName(ncName);
  130. }
  131. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlNmToken"]/*' />
  132. protected static string FromXmlNmToken(string nmToken) {
  133. return XmlCustomFormatter.FromXmlNmToken(nmToken);
  134. }
  135. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlNmTokens"]/*' />
  136. protected static string FromXmlNmTokens(string nmTokens) {
  137. return XmlCustomFormatter.FromXmlNmTokens(nmTokens);
  138. }
  139. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteXsiType"]/*' />
  140. protected void WriteXsiType(string name, string ns) {
  141. WriteAttribute("type", XmlSchema.InstanceNamespace, GetQualifiedName(name, ns));
  142. }
  143. XmlQualifiedName GetPrimitiveTypeName(Type type) {
  144. return GetPrimitiveTypeName(type, true);
  145. }
  146. XmlQualifiedName GetPrimitiveTypeName(Type type, bool throwIfUnknown) {
  147. XmlQualifiedName qname = GetPrimitiveTypeNameInternal(type);
  148. if (throwIfUnknown && qname == null)
  149. throw CreateUnknownTypeException(type);
  150. return qname;
  151. }
  152. internal static XmlQualifiedName GetPrimitiveTypeNameInternal(Type type) {
  153. string typeName;
  154. string typeNs = XmlSchema.Namespace;
  155. switch (Type.GetTypeCode(type)) {
  156. case TypeCode.String: typeName = "string"; break;
  157. case TypeCode.Int32: typeName = "int"; break;
  158. case TypeCode.Boolean: typeName = "boolean"; break;
  159. case TypeCode.Int16: typeName = "short"; break;
  160. case TypeCode.Int64: typeName = "long"; break;
  161. case TypeCode.Single: typeName = "float"; break;
  162. case TypeCode.Double: typeName = "double"; break;
  163. case TypeCode.Decimal: typeName = "decimal"; break;
  164. case TypeCode.DateTime: typeName = "dateTime"; break;
  165. case TypeCode.Byte: typeName = "unsignedByte"; break;
  166. case TypeCode.SByte: typeName = "byte"; break;
  167. case TypeCode.UInt16: typeName = "unsignedShort"; break;
  168. case TypeCode.UInt32: typeName = "unsignedInt"; break;
  169. case TypeCode.UInt64: typeName = "unsignedLong"; break;
  170. case TypeCode.Char:
  171. typeName = "char";
  172. typeNs = UrtTypes.Namespace;
  173. break;
  174. default:
  175. if (type == typeof(XmlQualifiedName)) typeName = "QName";
  176. else if (type == typeof(byte[])) typeName = "base64Binary";
  177. else if (type == typeof(TimeSpan) && LocalAppContextSwitches.EnableTimeSpanSerialization)
  178. typeName = "TimeSpan";
  179. else if (type == typeof(Guid)) {
  180. typeName = "guid";
  181. typeNs = UrtTypes.Namespace;
  182. }
  183. else if (type == typeof(XmlNode[])) {
  184. typeName = Soap.UrType;
  185. }
  186. else
  187. return null;
  188. break;
  189. }
  190. return new XmlQualifiedName(typeName, typeNs);
  191. }
  192. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteTypedPrimitive"]/*' />
  193. protected void WriteTypedPrimitive(string name, string ns, object o, bool xsiType) {
  194. string value = null;
  195. string type;
  196. string typeNs = XmlSchema.Namespace;
  197. bool writeRaw = true;
  198. bool writeDirect = false;
  199. Type t = o.GetType();
  200. bool wroteStartElement = false;
  201. switch (Type.GetTypeCode(t)) {
  202. case TypeCode.String:
  203. value = (string)o;
  204. type = "string";
  205. writeRaw = false;
  206. break;
  207. case TypeCode.Int32:
  208. value = XmlConvert.ToString((int)o);
  209. type = "int";
  210. break;
  211. case TypeCode.Boolean:
  212. value = XmlConvert.ToString((bool)o);
  213. type = "boolean";
  214. break;
  215. case TypeCode.Int16:
  216. value = XmlConvert.ToString((short)o);
  217. type = "short";
  218. break;
  219. case TypeCode.Int64:
  220. value = XmlConvert.ToString((long)o);
  221. type = "long";
  222. break;
  223. case TypeCode.Single:
  224. value = XmlConvert.ToString((float)o);
  225. type = "float";
  226. break;
  227. case TypeCode.Double:
  228. value = XmlConvert.ToString((double)o);
  229. type = "double";
  230. break;
  231. case TypeCode.Decimal:
  232. value = XmlConvert.ToString((decimal)o);
  233. type = "decimal";
  234. break;
  235. case TypeCode.DateTime:
  236. value = FromDateTime((DateTime)o);
  237. type = "dateTime";
  238. break;
  239. case TypeCode.Char:
  240. value = FromChar((char)o);
  241. type = "char";
  242. typeNs = UrtTypes.Namespace;
  243. break;
  244. case TypeCode.Byte:
  245. value = XmlConvert.ToString((byte)o);
  246. type = "unsignedByte";
  247. break;
  248. case TypeCode.SByte:
  249. value = XmlConvert.ToString((sbyte)o);
  250. type = "byte";
  251. break;
  252. case TypeCode.UInt16:
  253. value = XmlConvert.ToString((UInt16)o);
  254. type = "unsignedShort";
  255. break;
  256. case TypeCode.UInt32:
  257. value = XmlConvert.ToString((UInt32)o);
  258. type = "unsignedInt";
  259. break;
  260. case TypeCode.UInt64:
  261. value = XmlConvert.ToString((UInt64)o);
  262. type = "unsignedLong";
  263. break;
  264. default:
  265. if (t == typeof(XmlQualifiedName)) {
  266. type = "QName";
  267. // need to write start element ahead of time to establish context
  268. // for ns definitions by FromXmlQualifiedName
  269. wroteStartElement = true;
  270. if (name == null)
  271. w.WriteStartElement(type, typeNs);
  272. else
  273. w.WriteStartElement(name, ns);
  274. value = FromXmlQualifiedName((XmlQualifiedName)o, false);
  275. }
  276. else if (t == typeof(byte[])) {
  277. value = String.Empty;
  278. writeDirect = true;
  279. type = "base64Binary";
  280. }
  281. else if (t == typeof(Guid)) {
  282. value = XmlConvert.ToString((Guid)o);
  283. type = "guid";
  284. typeNs = UrtTypes.Namespace;
  285. }
  286. else if (t == typeof(TimeSpan) && LocalAppContextSwitches.EnableTimeSpanSerialization) {
  287. value = XmlConvert.ToString((TimeSpan)o);
  288. type = "TimeSpan";
  289. }
  290. else if (typeof(XmlNode[]).IsAssignableFrom(t)){
  291. if (name == null)
  292. w.WriteStartElement(Soap.UrType, XmlSchema.Namespace);
  293. else
  294. w.WriteStartElement(name, ns);
  295. XmlNode[] xmlNodes = (XmlNode[])o;
  296. for (int i=0;i<xmlNodes.Length;i++){
  297. if (xmlNodes[i] == null)
  298. continue;
  299. xmlNodes[i].WriteTo(w);
  300. }
  301. w.WriteEndElement();
  302. return;
  303. }
  304. else
  305. throw CreateUnknownTypeException(t);
  306. break;
  307. }
  308. if (!wroteStartElement) {
  309. if (name == null)
  310. w.WriteStartElement(type, typeNs);
  311. else
  312. w.WriteStartElement(name, ns);
  313. }
  314. if (xsiType) WriteXsiType(type, typeNs);
  315. if (value == null) {
  316. w.WriteAttributeString("nil", XmlSchema.InstanceNamespace, "true");
  317. }
  318. else if (writeDirect) {
  319. // only one type currently writes directly to XML stream
  320. XmlCustomFormatter.WriteArrayBase64(w, (byte[])o, 0,((byte[])o).Length);
  321. }
  322. else if(writeRaw) {
  323. w.WriteRaw(value);
  324. }
  325. else
  326. w.WriteString(value);
  327. w.WriteEndElement();
  328. }
  329. string GetQualifiedName(string name, string ns) {
  330. if (ns == null || ns.Length == 0) return name;
  331. string prefix = w.LookupPrefix(ns);
  332. if (prefix == null) {
  333. if (ns == XmlReservedNs.NsXml) {
  334. prefix = "xml";
  335. }
  336. else {
  337. prefix = NextPrefix();
  338. WriteAttribute("xmlns", prefix, null, ns);
  339. }
  340. }
  341. else if (prefix.Length == 0) {
  342. return name;
  343. }
  344. return prefix + ":" + name;
  345. }
  346. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlQualifiedName"]/*' />
  347. protected string FromXmlQualifiedName(XmlQualifiedName xmlQualifiedName) {
  348. return FromXmlQualifiedName(xmlQualifiedName, true);
  349. }
  350. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlQualifiedName"]/*' />
  351. protected string FromXmlQualifiedName(XmlQualifiedName xmlQualifiedName, bool ignoreEmpty) {
  352. if (xmlQualifiedName == null) return null;
  353. if (xmlQualifiedName.IsEmpty && ignoreEmpty) return null;
  354. return GetQualifiedName(EscapeName ? XmlConvert.EncodeLocalName(xmlQualifiedName.Name) : xmlQualifiedName.Name, xmlQualifiedName.Namespace);
  355. }
  356. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement"]/*' />
  357. protected void WriteStartElement(string name) {
  358. WriteStartElement(name, null, null, false, null);
  359. }
  360. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement1"]/*' />
  361. protected void WriteStartElement(string name, string ns) {
  362. WriteStartElement(name, ns, null, false, null);
  363. }
  364. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement4"]/*' />
  365. protected void WriteStartElement(string name, string ns, bool writePrefixed) {
  366. WriteStartElement(name, ns, null, writePrefixed, null);
  367. }
  368. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement2"]/*' />
  369. protected void WriteStartElement(string name, string ns, object o) {
  370. WriteStartElement(name, ns, o, false, null);
  371. }
  372. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement3"]/*' />
  373. protected void WriteStartElement(string name, string ns, object o, bool writePrefixed) {
  374. WriteStartElement(name, ns, o, writePrefixed, null);
  375. }
  376. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement5"]/*' />
  377. protected void WriteStartElement(string name, string ns, object o, bool writePrefixed, XmlSerializerNamespaces xmlns) {
  378. if (o != null && objectsInUse != null) {
  379. if (objectsInUse.ContainsKey(o)) throw new InvalidOperationException(Res.GetString(Res.XmlCircularReference, o.GetType().FullName));
  380. objectsInUse.Add(o, o);
  381. }
  382. string prefix = null;
  383. bool needEmptyDefaultNamespace = false;
  384. if (namespaces != null) {
  385. foreach(string alias in namespaces.Namespaces.Keys) {
  386. string aliasNs = (string)namespaces.Namespaces[alias];
  387. if (alias.Length > 0 && aliasNs == ns)
  388. prefix = alias;
  389. if (alias.Length == 0) {
  390. if (aliasNs == null || aliasNs.Length == 0)
  391. needEmptyDefaultNamespace = true;
  392. if (ns != aliasNs)
  393. writePrefixed = true;
  394. }
  395. }
  396. usedPrefixes = ListUsedPrefixes(namespaces.Namespaces, aliasBase);
  397. }
  398. if (writePrefixed && prefix == null && ns != null && ns.Length > 0) {
  399. prefix = w.LookupPrefix(ns);
  400. if (prefix == null || prefix.Length == 0) {
  401. prefix = NextPrefix();
  402. }
  403. }
  404. if (prefix == null && xmlns != null) {
  405. prefix = xmlns.LookupPrefix(ns);
  406. }
  407. if (needEmptyDefaultNamespace && prefix == null && ns != null && ns.Length != 0)
  408. prefix = NextPrefix();
  409. w.WriteStartElement(prefix, name, ns);
  410. if (namespaces != null) {
  411. foreach(string alias in namespaces.Namespaces.Keys) {
  412. string aliasNs = (string)namespaces.Namespaces[alias];
  413. if (alias.Length == 0 && (aliasNs == null || aliasNs.Length == 0))
  414. continue;
  415. if (aliasNs == null || aliasNs.Length == 0) {
  416. if (alias.Length > 0)
  417. throw new InvalidOperationException(Res.GetString(Res.XmlInvalidXmlns, alias));
  418. WriteAttribute("xmlns", alias, null, aliasNs);
  419. }
  420. else {
  421. if (w.LookupPrefix(aliasNs) == null) {
  422. // write the default namespace declaration only if we have not written it already, over wise we just ignore one provided by the user
  423. if (prefix == null && alias.Length == 0)
  424. break;
  425. WriteAttribute("xmlns", alias, null, aliasNs);
  426. }
  427. }
  428. }
  429. }
  430. WriteNamespaceDeclarations(xmlns);
  431. }
  432. Hashtable ListUsedPrefixes(Hashtable nsList, string prefix) {
  433. Hashtable qnIndexes = new Hashtable();
  434. int prefixLength = prefix.Length;
  435. const string MaxInt32 = "2147483647";
  436. foreach(string alias in namespaces.Namespaces.Keys) {
  437. string name;
  438. if (alias.Length > prefixLength) {
  439. name = alias;
  440. int nameLength = name.Length;
  441. if (name.Length > prefixLength && name.Length <= prefixLength + MaxInt32.Length && name.StartsWith(prefix, StringComparison.Ordinal)) {
  442. bool numeric = true;
  443. for (int j = prefixLength; j < name.Length; j++) {
  444. if (!Char.IsDigit(name, j)) {
  445. numeric = false;
  446. break;
  447. }
  448. }
  449. if (numeric) {
  450. Int64 index = Int64.Parse(name.Substring(prefixLength), CultureInfo.InvariantCulture);
  451. if (index <= Int32.MaxValue) {
  452. Int32 newIndex = (Int32)index;
  453. if (!qnIndexes.ContainsKey(newIndex)) {
  454. qnIndexes.Add(newIndex, newIndex);
  455. }
  456. }
  457. }
  458. }
  459. }
  460. }
  461. if (qnIndexes.Count > 0) {
  462. return qnIndexes;
  463. }
  464. return null;
  465. }
  466. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullTagEncoded"]/*' />
  467. protected void WriteNullTagEncoded(string name) {
  468. WriteNullTagEncoded(name, null);
  469. }
  470. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullTagEncoded1"]/*' />
  471. protected void WriteNullTagEncoded(string name, string ns) {
  472. if (name == null || name.Length == 0)
  473. return;
  474. WriteStartElement(name, ns, null, true);
  475. w.WriteAttributeString("nil", XmlSchema.InstanceNamespace, "true");
  476. w.WriteEndElement();
  477. }
  478. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullTagLiteral"]/*' />
  479. protected void WriteNullTagLiteral(string name) {
  480. WriteNullTagLiteral(name, null);
  481. }
  482. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullTag1"]/*' />
  483. protected void WriteNullTagLiteral(string name, string ns) {
  484. if (name == null || name.Length == 0)
  485. return;
  486. WriteStartElement(name, ns, null, false);
  487. w.WriteAttributeString("nil", XmlSchema.InstanceNamespace, "true");
  488. w.WriteEndElement();
  489. }
  490. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteEmptyTag"]/*' />
  491. protected void WriteEmptyTag(string name) {
  492. WriteEmptyTag(name, null);
  493. }
  494. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteEmptyTag1"]/*' />
  495. protected void WriteEmptyTag(string name, string ns) {
  496. if (name == null || name.Length == 0)
  497. return;
  498. WriteStartElement(name, ns, null, false);
  499. w.WriteEndElement();
  500. }
  501. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteEndElement"]/*' />
  502. protected void WriteEndElement() {
  503. w.WriteEndElement();
  504. }
  505. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteEndElement1"]/*' />
  506. protected void WriteEndElement(object o) {
  507. w.WriteEndElement();
  508. if (o != null && objectsInUse != null) {
  509. #if DEBUG
  510. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  511. if (!objectsInUse.ContainsKey(o)) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "missing stack object of type " + o.GetType().FullName));
  512. #endif
  513. objectsInUse.Remove(o);
  514. }
  515. }
  516. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteSerializable"]/*' />
  517. protected void WriteSerializable(IXmlSerializable serializable, string name, string ns, bool isNullable) {
  518. WriteSerializable(serializable, name, ns, isNullable, true);
  519. }
  520. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteSerializable1"]/*' />
  521. protected void WriteSerializable(IXmlSerializable serializable, string name, string ns, bool isNullable, bool wrapped) {
  522. if (serializable == null) {
  523. if (isNullable) WriteNullTagLiteral(name, ns);
  524. return;
  525. }
  526. if (wrapped) {
  527. w.WriteStartElement(name, ns);
  528. }
  529. serializable.WriteXml(w);
  530. if (wrapped) {
  531. w.WriteEndElement();
  532. }
  533. }
  534. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringEncoded"]/*' />
  535. protected void WriteNullableStringEncoded(string name, string ns, string value, XmlQualifiedName xsiType) {
  536. if (value == null)
  537. WriteNullTagEncoded(name, ns);
  538. else
  539. WriteElementString(name, ns, value, xsiType);
  540. }
  541. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringLiteral"]/*' />
  542. protected void WriteNullableStringLiteral(string name, string ns, string value) {
  543. if (value == null)
  544. WriteNullTagLiteral(name, ns);
  545. else
  546. WriteElementString(name, ns, value, null);
  547. }
  548. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringEncodedRaw"]/*' />
  549. protected void WriteNullableStringEncodedRaw(string name, string ns, string value, XmlQualifiedName xsiType) {
  550. if (value == null)
  551. WriteNullTagEncoded(name, ns);
  552. else
  553. WriteElementStringRaw(name, ns, value, xsiType);
  554. }
  555. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringEncodedRaw1"]/*' />
  556. protected void WriteNullableStringEncodedRaw(string name, string ns, byte[] value, XmlQualifiedName xsiType) {
  557. if (value == null)
  558. WriteNullTagEncoded(name, ns);
  559. else
  560. WriteElementStringRaw(name, ns, value, xsiType);
  561. }
  562. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringLiteralRaw"]/*' />
  563. protected void WriteNullableStringLiteralRaw(string name, string ns, string value) {
  564. if (value == null)
  565. WriteNullTagLiteral(name, ns);
  566. else
  567. WriteElementStringRaw(name, ns, value, null);
  568. }
  569. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringLiteralRaw1"]/*' />
  570. protected void WriteNullableStringLiteralRaw(string name, string ns, byte[] value) {
  571. if (value == null)
  572. WriteNullTagLiteral(name, ns);
  573. else
  574. WriteElementStringRaw(name, ns, value, null);
  575. }
  576. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableQualifiedNameEncoded"]/*' />
  577. /// <devdoc>
  578. /// <para>[To be supplied.]</para>
  579. /// </devdoc>
  580. protected void WriteNullableQualifiedNameEncoded(string name, string ns, XmlQualifiedName value, XmlQualifiedName xsiType) {
  581. if (value == null)
  582. WriteNullTagEncoded(name, ns);
  583. else
  584. WriteElementQualifiedName(name, ns, value, xsiType);
  585. }
  586. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableQualifiedNameLiteral"]/*' />
  587. /// <devdoc>
  588. /// <para>[To be supplied.]</para>
  589. /// </devdoc>
  590. protected void WriteNullableQualifiedNameLiteral(string name, string ns, XmlQualifiedName value) {
  591. if (value == null)
  592. WriteNullTagLiteral(name, ns);
  593. else
  594. WriteElementQualifiedName(name, ns, value, null);
  595. }
  596. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementEncoded"]/*' />
  597. protected void WriteElementEncoded(XmlNode node, string name, string ns, bool isNullable, bool any) {
  598. if (node == null) {
  599. if (isNullable) WriteNullTagEncoded(name, ns);
  600. return;
  601. }
  602. WriteElement(node, name, ns, isNullable, any);
  603. }
  604. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementLiteral"]/*' />
  605. protected void WriteElementLiteral(XmlNode node, string name, string ns, bool isNullable, bool any) {
  606. if (node == null) {
  607. if (isNullable) WriteNullTagLiteral(name, ns);
  608. return;
  609. }
  610. WriteElement(node, name, ns, isNullable, any);
  611. }
  612. private void WriteElement(XmlNode node, string name, string ns, bool isNullable, bool any) {
  613. if (typeof(XmlAttribute).IsAssignableFrom(node.GetType()))
  614. throw new InvalidOperationException(Res.GetString(Res.XmlNoAttributeHere));
  615. if (node is XmlDocument) {
  616. node = ((XmlDocument)node).DocumentElement;
  617. if (node == null) {
  618. if (isNullable) WriteNullTagEncoded(name, ns);
  619. return;
  620. }
  621. }
  622. if (any) {
  623. if (node is XmlElement && name != null && name.Length > 0) {
  624. // need to check against schema
  625. if (node.LocalName != name || node.NamespaceURI != ns)
  626. throw new InvalidOperationException(Res.GetString(Res.XmlElementNameMismatch, node.LocalName, node.NamespaceURI, name, ns));
  627. }
  628. }
  629. else
  630. w.WriteStartElement(name, ns);
  631. node.WriteTo(w);
  632. if (!any)
  633. w.WriteEndElement();
  634. }
  635. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateUnknownTypeException"]/*' />
  636. protected Exception CreateUnknownTypeException(object o) {
  637. return CreateUnknownTypeException(o.GetType());
  638. }
  639. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateUnknownTypeException1"]/*' />
  640. protected Exception CreateUnknownTypeException(Type type) {
  641. if (typeof(IXmlSerializable).IsAssignableFrom(type)) return new InvalidOperationException(Res.GetString(Res.XmlInvalidSerializable, type.FullName));
  642. TypeDesc typeDesc = new TypeScope().GetTypeDesc(type);
  643. if (!typeDesc.IsStructLike) return new InvalidOperationException(Res.GetString(Res.XmlInvalidUseOfType, type.FullName));
  644. return new InvalidOperationException(Res.GetString(Res.XmlUnxpectedType, type.FullName));
  645. }
  646. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateMismatchChoiceException"]/*' />
  647. protected Exception CreateMismatchChoiceException(string value, string elementName, string enumValue) {
  648. // Value of {0} mismatches the type of {1}, you need to set it to {2}.
  649. return new InvalidOperationException(Res.GetString(Res.XmlChoiceMismatchChoiceException, elementName, value, enumValue));
  650. }
  651. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateUnknownAnyElementException"]/*' />
  652. protected Exception CreateUnknownAnyElementException(string name, string ns) {
  653. return new InvalidOperationException(Res.GetString(Res.XmlUnknownAnyElement, name, ns));
  654. }
  655. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateInvalidChoiceIdentifierValueException"]/*' />
  656. protected Exception CreateInvalidChoiceIdentifierValueException(string type, string identifier) {
  657. return new InvalidOperationException(Res.GetString(Res.XmlInvalidChoiceIdentifierValue, type, identifier));
  658. }
  659. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateChoiceIdentifierValueException"]/*' />
  660. protected Exception CreateChoiceIdentifierValueException(string value, string identifier, string name, string ns) {
  661. // XmlChoiceIdentifierMismatch=Value '{0}' of the choice identifier '{1}' does not match element '{2}' from namespace '{3}'.
  662. return new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentifierMismatch, value, identifier, name, ns));
  663. }
  664. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateInvalidEnumValueException"]/*' />
  665. protected Exception CreateInvalidEnumValueException(object value, string typeName) {
  666. return new InvalidOperationException(Res.GetString(Res.XmlUnknownConstant, value, typeName));
  667. }
  668. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateInvalidAnyTypeException"]/*' />
  669. protected Exception CreateInvalidAnyTypeException(object o) {
  670. return CreateInvalidAnyTypeException(o.GetType());
  671. }
  672. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateInvalidAnyTypeException1"]/*' />
  673. protected Exception CreateInvalidAnyTypeException(Type type) {
  674. return new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, type.FullName));
  675. }
  676. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteReferencingElement"]/*' />
  677. protected void WriteReferencingElement(string n, string ns, object o) {
  678. WriteReferencingElement(n, ns, o, false);
  679. }
  680. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteReferencingElement1"]/*' />
  681. protected void WriteReferencingElement(string n, string ns, object o, bool isNullable) {
  682. if (o == null) {
  683. if (isNullable) WriteNullTagEncoded(n, ns);
  684. return;
  685. }
  686. WriteStartElement(n, ns, null, true);
  687. if (soap12)
  688. w.WriteAttributeString("ref", Soap12.Encoding, GetId(o, true));
  689. else
  690. w.WriteAttributeString("href", "#" + GetId(o, true));
  691. w.WriteEndElement();
  692. }
  693. bool IsIdDefined(object o) {
  694. if (references != null) return references.Contains(o);
  695. else return false;
  696. }
  697. string GetId(object o, bool addToReferencesList) {
  698. if (references == null) {
  699. references = new Hashtable();
  700. referencesToWrite = new ArrayList();
  701. }
  702. string id = (string)references[o];
  703. if (id == null) {
  704. id = idBase + "id" + (++nextId).ToString(CultureInfo.InvariantCulture);
  705. references.Add(o, id);
  706. if (addToReferencesList) referencesToWrite.Add(o);
  707. }
  708. return id;
  709. }
  710. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteId"]/*' />
  711. protected void WriteId(object o) {
  712. WriteId(o, true);
  713. }
  714. void WriteId(object o, bool addToReferencesList) {
  715. if (soap12)
  716. w.WriteAttributeString("id", Soap12.Encoding, GetId(o, addToReferencesList));
  717. else
  718. w.WriteAttributeString("id", GetId(o, addToReferencesList));
  719. }
  720. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteXmlAttribute1"]/*' />
  721. protected void WriteXmlAttribute(XmlNode node) {
  722. WriteXmlAttribute(node, null);
  723. }
  724. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteXmlAttribute2"]/*' />
  725. protected void WriteXmlAttribute(XmlNode node, object container) {
  726. XmlAttribute attr = node as XmlAttribute;
  727. if (attr == null) throw new InvalidOperationException(Res.GetString(Res.XmlNeedAttributeHere));
  728. if (attr.Value != null) {
  729. if (attr.NamespaceURI == Wsdl.Namespace && attr.LocalName == Wsdl.ArrayType) {
  730. string dims;
  731. XmlQualifiedName qname = TypeScope.ParseWsdlArrayType(attr.Value, out dims, (container is XmlSchemaObject) ? (XmlSchemaObject)container : null);
  732. string value = FromXmlQualifiedName(qname, true) + dims;
  733. //<xsd:attribute xmlns:q3="s0" wsdl:arrayType="q3:FoosBase[]" xmlns:q4="http://schemas.xmlsoap.org/soap/encoding/" ref="q4:arrayType" />
  734. WriteAttribute(Wsdl.ArrayType, Wsdl.Namespace, value);
  735. }
  736. else {
  737. WriteAttribute(attr.Name, attr.NamespaceURI, attr.Value);
  738. }
  739. }
  740. }
  741. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute"]/*' />
  742. protected void WriteAttribute(string localName, string ns, string value) {
  743. if (value == null) return;
  744. if (localName == "xmlns" || localName.StartsWith("xmlns:", StringComparison.Ordinal)) {
  745. ;
  746. }
  747. else {
  748. int colon = localName.IndexOf(':');
  749. if (colon < 0) {
  750. if (ns == XmlReservedNs.NsXml) {
  751. string prefix = w.LookupPrefix(ns);
  752. if (prefix == null || prefix.Length == 0)
  753. prefix = "xml";
  754. w.WriteAttributeString(prefix, localName, ns, value);
  755. }
  756. else {
  757. w.WriteAttributeString(localName, ns, value);
  758. }
  759. }
  760. else {
  761. string prefix = localName.Substring(0, colon);
  762. w.WriteAttributeString(prefix, localName.Substring(colon+1), ns, value);
  763. }
  764. }
  765. }
  766. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute0"]/*' />
  767. protected void WriteAttribute(string localName, string ns, byte[] value) {
  768. if (value == null) return;
  769. if (localName == "xmlns" || localName.StartsWith("xmlns:", StringComparison.Ordinal)) {
  770. ;
  771. }
  772. else {
  773. int colon = localName.IndexOf(':');
  774. if (colon < 0) {
  775. if (ns == XmlReservedNs.NsXml) {
  776. string prefix = w.LookupPrefix(ns);
  777. if (prefix == null || prefix.Length == 0)
  778. prefix = "xml";
  779. w.WriteStartAttribute("xml", localName, ns);
  780. }
  781. else {
  782. w.WriteStartAttribute(null, localName, ns);
  783. }
  784. }
  785. else {
  786. string prefix = localName.Substring(0, colon);
  787. prefix = w.LookupPrefix(ns);
  788. w.WriteStartAttribute(prefix, localName.Substring(colon+1), ns);
  789. }
  790. XmlCustomFormatter.WriteArrayBase64(w, value, 0, value.Length);
  791. w.WriteEndAttribute();
  792. }
  793. }
  794. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute1"]/*' />
  795. protected void WriteAttribute(string localName, string value) {
  796. if (value == null) return;
  797. w.WriteAttributeString(localName, null, value);
  798. }
  799. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute01"]/*' />
  800. protected void WriteAttribute(string localName, byte[] value) {
  801. if (value == null) return;
  802. w.WriteStartAttribute(null, localName, (string)null);
  803. XmlCustomFormatter.WriteArrayBase64(w, value, 0, value.Length);
  804. w.WriteEndAttribute();
  805. }
  806. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute2"]/*' />
  807. protected void WriteAttribute(string prefix, string localName, string ns, string value) {
  808. if (value == null) return;
  809. w.WriteAttributeString(prefix, localName, null, value);
  810. }
  811. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteValue"]/*' />
  812. protected void WriteValue(string value) {
  813. if (value == null) return;
  814. w.WriteString(value);
  815. }
  816. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteValue01"]/*' />
  817. protected void WriteValue(byte[] value) {
  818. if (value == null) return;
  819. XmlCustomFormatter.WriteArrayBase64(w, value, 0, value.Length);
  820. }
  821. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartDocument"]/*' />
  822. protected void WriteStartDocument() {
  823. if (w.WriteState == WriteState.Start) {
  824. w.WriteStartDocument();
  825. }
  826. }
  827. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementString"]/*' />
  828. protected void WriteElementString(String localName, String value) {
  829. WriteElementString(localName, null, value, null);
  830. }
  831. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementString1"]/*' />
  832. protected void WriteElementString(String localName, String ns, String value) {
  833. WriteElementString(localName, ns, value, null);
  834. }
  835. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementString2"]/*' />
  836. protected void WriteElementString(String localName, String value, XmlQualifiedName xsiType) {
  837. WriteElementString(localName, null, value, xsiType);
  838. }
  839. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementString3"]/*' />
  840. protected void WriteElementString(String localName, String ns, String value, XmlQualifiedName xsiType) {
  841. if (value == null) return;
  842. if (xsiType == null)
  843. w.WriteElementString(localName, ns, value);
  844. else {
  845. w.WriteStartElement(localName, ns);
  846. WriteXsiType(xsiType.Name, xsiType.Namespace);
  847. w.WriteString(value);
  848. w.WriteEndElement();
  849. }
  850. }
  851. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw"]/*' />
  852. protected void WriteElementStringRaw(String localName, String value) {
  853. WriteElementStringRaw(localName,null,value, null);
  854. }
  855. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw0"]/*' />
  856. protected void WriteElementStringRaw(String localName, byte[] value) {
  857. WriteElementStringRaw(localName,null,value, null);
  858. }
  859. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw1"]/*' />
  860. protected void WriteElementStringRaw(String localName, String ns, String value) {
  861. WriteElementStringRaw(localName, ns, value, null);
  862. }
  863. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw01"]/*' />
  864. protected void WriteElementStringRaw(String localName, String ns, byte[] value) {
  865. WriteElementStringRaw(localName, ns, value, null);
  866. }
  867. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw2"]/*' />
  868. protected void WriteElementStringRaw(String localName, String value, XmlQualifiedName xsiType) {
  869. WriteElementStringRaw(localName,null,value, xsiType);
  870. }
  871. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw02"]/*' />
  872. protected void WriteElementStringRaw(String localName, byte[] value, XmlQualifiedName xsiType) {
  873. WriteElementStringRaw(localName, null, value, xsiType);
  874. }
  875. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw3"]/*' />
  876. protected void WriteElementStringRaw(String localName, String ns, String value, XmlQualifiedName xsiType) {
  877. if (value == null) return;
  878. w.WriteStartElement(localName, ns);
  879. if (xsiType != null)
  880. WriteXsiType(xsiType.Name, xsiType.Namespace);
  881. w.WriteRaw(value);
  882. w.WriteEndElement();
  883. }
  884. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw03"]/*' />
  885. protected void WriteElementStringRaw(String localName, String ns, byte[] value, XmlQualifiedName xsiType) {
  886. if (value == null) return;
  887. w.WriteStartElement(localName, ns);
  888. if (xsiType != null)
  889. WriteXsiType(xsiType.Name, xsiType.Namespace);
  890. XmlCustomFormatter.WriteArrayBase64(w, value, 0, value.Length);
  891. w.WriteEndElement();
  892. }
  893. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteRpcResult"]/*' />
  894. protected void WriteRpcResult(string name, string ns) {
  895. if (!soap12) return;
  896. WriteElementQualifiedName(Soap12.RpcResult, Soap12.RpcNamespace, new XmlQualifiedName(name, ns), null);
  897. }
  898. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementQualifiedName"]/*' />
  899. /// <devdoc>
  900. /// <para>[To be supplied.]</para>
  901. /// </devdoc>
  902. protected void WriteElementQualifiedName(String localName, XmlQualifiedName value) {
  903. WriteElementQualifiedName(localName,null,value, null);
  904. }
  905. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementQualifiedName1"]/*' />
  906. protected void WriteElementQualifiedName(string localName, XmlQualifiedName value, XmlQualifiedName xsiType) {
  907. WriteElementQualifiedName(localName, null, value, xsiType);
  908. }
  909. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementQualifiedName2"]/*' />
  910. /// <devdoc>
  911. /// <para>[To be supplied.]</para>
  912. /// </devdoc>
  913. protected void WriteElementQualifiedName(String localName, String ns, XmlQualifiedName value) {
  914. WriteElementQualifiedName(localName, ns, value, null);
  915. }
  916. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementQualifiedName3"]/*' />
  917. protected void WriteElementQualifiedName(string localName, string ns, XmlQualifiedName value, XmlQualifiedName xsiType) {
  918. if (value == null) return;
  919. if (value.Namespace == null || value.Namespace.Length == 0) {
  920. WriteStartElement(localName, ns, null, true);
  921. WriteAttribute("xmlns", "");
  922. }
  923. else
  924. w.WriteStartElement(localName, ns);
  925. if (xsiType != null)
  926. WriteXsiType(xsiType.Name, xsiType.Namespace);
  927. w.WriteString(FromXmlQualifiedName(value, false));
  928. w.WriteEndElement();
  929. }
  930. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.AddWriteCallback"]/*' />
  931. protected void AddWriteCallback(Type type, string typeName, string typeNs, XmlSerializationWriteCallback callback) {
  932. TypeEntry entry = new TypeEntry();
  933. entry.typeName = typeName;
  934. entry.typeNs = typeNs;
  935. entry.type = type;
  936. entry.callback = callback;
  937. typeEntries[type] = entry;
  938. }
  939. void WriteArray(string name, string ns, object o, Type type) {
  940. Type elementType = TypeScope.GetArrayElementType(type, null);
  941. string typeName;
  942. string typeNs;
  943. StringBuilder arrayDims = new StringBuilder();
  944. if (!soap12) {
  945. while ((elementType.IsArray || typeof(IEnumerable).IsAssignableFrom(elementType)) && GetPrimitiveTypeName(elementType, false) == null) {
  946. elementType = TypeScope.GetArrayElementType(elementType, null);
  947. arrayDims.Append("[]");
  948. }
  949. }
  950. if (elementType == typeof(object)) {
  951. typeName = Soap.UrType;
  952. typeNs = XmlSchema.Namespace;
  953. }
  954. else {
  955. TypeEntry entry = GetTypeEntry(elementType);
  956. if (entry != null) {
  957. typeName = entry.typeName;
  958. typeNs = entry.typeNs;
  959. }
  960. else if (soap12) {
  961. XmlQualifiedName qualName = GetPrimitiveTypeName(elementType, false);
  962. if (qualName != null) {
  963. typeName = qualName.Name;
  964. typeNs = qualName.Namespace;
  965. }
  966. else {
  967. Type elementBaseType = elementType.BaseType;
  968. while (elementBaseType != null) {
  969. entry = GetTypeEntry(elementBaseType);
  970. if (entry != null) break;
  971. elementBaseType = elementBaseType.BaseType;
  972. }
  973. if (entry != null) {
  974. typeName = entry.typeName;
  975. typeNs = entry.typeNs;
  976. }
  977. else {
  978. typeName = Soap.UrType;
  979. typeNs = XmlSchema.Namespace;
  980. }
  981. }
  982. }
  983. else {
  984. XmlQualifiedName qualName = GetPrimitiveTypeName(elementType);
  985. typeName = qualName.Name;
  986. typeNs = qualName.Namespace;
  987. }
  988. }
  989. if (arrayDims.Length > 0)
  990. typeName = typeName + arrayDims.ToString();
  991. if (soap12 && name != null && name.Length > 0)
  992. WriteStartElement(name, ns, null, false);
  993. else
  994. WriteStartElement(Soap.Array, Soap.Encoding, null, true);
  995. WriteId(o, false);
  996. if (type.IsArray) {
  997. Array a = (Array)o;
  998. int arrayLength = a.Length;
  999. if (soap12) {
  1000. w.WriteAttributeString("itemType", Soap12.Encoding, GetQualifiedName(typeName, typeNs));
  1001. w.WriteAttributeString("arraySize", Soap12.Encoding, arrayLength.ToString(CultureInfo.InvariantCulture));
  1002. }
  1003. else {
  1004. w.WriteAttributeString("arrayType", Soap.Encoding, GetQualifiedName(typeName, typeNs) + "[" + arrayLength.ToString(CultureInfo.InvariantCulture) + "]");
  1005. }
  1006. for (int i = 0; i < arrayLength; i++) {
  1007. WritePotentiallyReferencingElement("Item", "", a.GetValue(i), elementType, false, true);
  1008. }
  1009. }
  1010. else {
  1011. #if DEBUG
  1012. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  1013. if (!typeof(IEnumerable).IsAssignableFrom(type)) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "not array like type " + type.FullName));
  1014. #endif
  1015. int arrayLength = typeof(ICollection).IsAssignableFrom(type) ? ((ICollection)o).Count : -1;
  1016. if (soap12) {
  1017. w.WriteAttributeString("itemType", Soap12.Encoding, GetQualifiedName(typeName, typeNs));
  1018. if (arrayLength >= 0)
  1019. w.WriteAttributeString("arraySize", Soap12.Encoding, arrayLength.ToString(CultureInfo.InvariantCulture));
  1020. }
  1021. else {
  1022. string brackets = arrayLength >= 0 ? "[" + arrayLength + "]" : "[]";
  1023. w.WriteAttributeString("arrayType", Soap.Encoding, GetQualifiedName(typeName, typeNs) + brackets);
  1024. }
  1025. IEnumerator e = ((IEnumerable)o).GetEnumerator();
  1026. if (e != null) {
  1027. while (e.MoveNext()) {
  1028. WritePotentiallyReferencingElement("Item", "", e.Current, elementType, false, true);
  1029. }
  1030. }
  1031. }
  1032. w.WriteEndElement();
  1033. }
  1034. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WritePotentiallyReferencingElement"]/*' />
  1035. protected void WritePotentiallyReferencingElement(string n, string ns, object o) {
  1036. WritePotentiallyReferencingElement(n, ns, o, null, false, false);
  1037. }
  1038. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WritePotentiallyReferencingElement1"]/*' />
  1039. protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType) {
  1040. WritePotentiallyReferencingElement(n, ns, o, ambientType, false, false);
  1041. }
  1042. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WritePotentiallyReferencingElement2"]/*' />
  1043. protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType, bool suppressReference) {
  1044. WritePotentiallyReferencingElement(n, ns, o, ambientType, suppressReference, false);
  1045. }
  1046. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WritePotentiallyReferencingElement3"]/*' />
  1047. protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType, bool suppressReference, bool isNullable) {
  1048. if (o == null) {
  1049. if (isNullable) WriteNullTagEncoded(n, ns);
  1050. return;
  1051. }
  1052. Type t = o.GetType();
  1053. if (Convert.GetTypeCode(o) == TypeCode.Object && !(o is Guid) && (t != typeof(XmlQualifiedName)) && !(o is XmlNode[]) && (t != typeof(byte[]))) {
  1054. if ((suppressReference || soap12) && !IsIdDefined(o)) {
  1055. WriteReferencedElement(n, ns, o, ambientType);
  1056. }
  1057. else {
  1058. if (n == null) {
  1059. TypeEntry entry = GetTypeEntry(t);
  1060. WriteReferencingElement(entry.typeName, entry.typeNs, o, isNullable);
  1061. }
  1062. else
  1063. WriteReferencingElement(n, ns, o, isNullable);
  1064. }
  1065. }
  1066. else {
  1067. // Enums always write xsi:type, so don't write it again here.
  1068. bool needXsiType = t != ambientType && !t.IsEnum;
  1069. TypeEntry entry = GetTypeEntry(t);
  1070. if (entry != null) {
  1071. if (n == null)
  1072. WriteStartElement(entry.typeName, entry.typeNs, null, true);
  1073. else
  1074. WriteStartElement(n, ns, null, true);
  1075. if (needXsiType) WriteXsiType(entry.typeName, entry.typeNs);
  1076. entry.callback(o);
  1077. w.WriteEndElement();
  1078. }
  1079. else {
  1080. WriteTypedPrimitive(n, ns, o, needXsiType);
  1081. }
  1082. }
  1083. }
  1084. void WriteReferencedElement(object o, Type ambientType) {
  1085. WriteReferencedElement(null, null, o, ambientType);
  1086. }
  1087. void WriteReferencedElement(string name, string ns, object o, Type ambientType) {
  1088. if (name == null) name = String.Empty;
  1089. Type t = o.GetType();
  1090. if (t.IsArray || typeof(IEnumerable).IsAssignableFrom(t)) {
  1091. WriteArray(name, ns, o, t);
  1092. }
  1093. else {
  1094. TypeEntry entry = GetTypeEntry(t);
  1095. if (entry == null) throw CreateUnknownTypeException(t);
  1096. WriteStartElement(name.Length == 0 ? entry.typeName : name, ns == null ? entry.typeNs : ns, null, true);
  1097. WriteId(o, false);
  1098. if (ambientType != t) WriteXsiType(entry.typeName, entry.typeNs);
  1099. entry.callback(o);
  1100. w.WriteEndElement();
  1101. }
  1102. }
  1103. TypeEntry GetTypeEntry(Type t) {
  1104. if (typeEntries == null) {
  1105. typeEntries = new Hashtable();
  1106. InitCallbacks();
  1107. }
  1108. return (TypeEntry)typeEntries[t];
  1109. }
  1110. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.InitCallbacks"]/*' />
  1111. protected abstract void InitCallbacks();
  1112. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteReferencedElements"]/*' />
  1113. protected void WriteReferencedElements() {
  1114. if (referencesToWrite == null) return;
  1115. for (int i = 0; i < referencesToWrite.Count; i++) {
  1116. WriteReferencedElement(referencesToWrite[i], null);
  1117. }
  1118. }
  1119. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.TopLevelElement"]/*' />
  1120. protected void TopLevelElement() {
  1121. objectsInUse = new Hashtable();
  1122. }
  1123. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNamespaceDeclarations"]/*' />
  1124. ///<internalonly/>
  1125. protected void WriteNamespaceDeclarations(XmlSerializerNamespaces xmlns) {
  1126. if (xmlns != null) {
  1127. foreach (DictionaryEntry entry in xmlns.Namespaces) {
  1128. string prefix = (string)entry.Key;
  1129. string ns = (string)entry.Value;
  1130. if (namespaces != null) {
  1131. string oldNs = namespaces.Namespaces[prefix] as string;
  1132. if (oldNs != null && oldNs != ns) {
  1133. throw new InvalidOperationException(Res.GetString(Res.XmlDuplicateNs, prefix, ns));
  1134. }
  1135. }
  1136. string oldPrefix = (ns == null || ns.Length == 0) ? null : Writer.LookupPrefix(ns);
  1137. if (oldPrefix == null || oldPrefix != prefix) {
  1138. WriteAttribute("xmlns", prefix, null, ns);
  1139. }
  1140. }
  1141. }
  1142. namespaces = null;
  1143. }
  1144. string NextPrefix() {
  1145. if (usedPrefixes == null) {
  1146. return aliasBase + (++tempNamespacePrefix);
  1147. }
  1148. while (usedPrefixes.ContainsKey(++tempNamespacePrefix)) {;}
  1149. return aliasBase + tempNamespacePrefix;
  1150. }
  1151. internal class TypeEntry {
  1152. internal XmlSerializationWriteCallback callback;
  1153. internal string typeNs;
  1154. internal string typeName;
  1155. internal Type type;
  1156. }
  1157. }
  1158. /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriteCallback"]/*' />
  1159. ///<internalonly/>
  1160. public delegate void XmlSerializationWriteCallback(object o);
  1161. internal class XmlSerializationWriterCodeGen : XmlSerializationCodeGen {
  1162. internal XmlSerializationWriterCodeGen(IndentedWriter writer, TypeScope[] scopes, string access, string className) : base(writer, scopes, access, className){
  1163. }
  1164. internal void GenerateBegin() {
  1165. Writer.Write(Access);
  1166. Writer.Write(" class ");
  1167. Writer.Write(ClassName);
  1168. Writer.Write(" : ");
  1169. Writer.Write(typeof(XmlSerializationWriter).FullName);
  1170. Writer.WriteLine(" {");
  1171. Writer.Indent++;
  1172. foreach (TypeScope scope in Scopes) {
  1173. foreach (TypeMapping mapping in scope.TypeMappings) {
  1174. if (mapping is StructMapping || mapping is EnumMapping){
  1175. MethodNames.Add(mapping, NextMethodName(mapping.TypeDesc.Name));
  1176. }
  1177. }
  1178. RaCodeGen.WriteReflectionInit(scope);
  1179. }
  1180. // pre-generate write methods only for the encoded soap
  1181. foreach (TypeScope scope in Scopes) {
  1182. foreach (TypeMapping mapping in scope.TypeMappings) {
  1183. if (!mapping.IsSoap)
  1184. continue;
  1185. if (mapping is StructMapping)
  1186. WriteStructMethod((StructMapping)mapping);
  1187. else if (mapping is EnumMapping)
  1188. WriteEnumMethod((EnumMapping)mapping);
  1189. }
  1190. }
  1191. }
  1192. internal override void GenerateMethod(TypeMapping mapping) {
  1193. if (GeneratedMethods.Contains(mapping))
  1194. return;
  1195. GeneratedMethods[mapping] = mapping;
  1196. if (mapping is StructMapping) {
  1197. WriteStructMethod((StructMapping)mapping);
  1198. }
  1199. else if (mapping is EnumMapping) {
  1200. WriteEnumMethod((EnumMapping)mapping);
  1201. }
  1202. }
  1203. internal void GenerateEnd() {
  1204. GenerateReferencedMethods();
  1205. GenerateInitCallbacksMethod();
  1206. Writer.Indent--;
  1207. Writer.WriteLine("}");
  1208. }
  1209. internal string GenerateElement(XmlMapping xmlMapping) {
  1210. if (!xmlMapping.IsWriteable)
  1211. return null;
  1212. if (!xmlMapping.GenerateSerializer)
  1213. throw new ArgumentException(Res.GetString(Res.XmlInternalError), "xmlMapping");
  1214. if (xmlMapping is XmlTypeMapping)
  1215. return GenerateTypeElement((XmlTypeMapping)xmlMapping);
  1216. else if (xmlMapping is XmlMembersMapping)
  1217. return GenerateMembersElement((XmlMembersMapping)xmlMapping);
  1218. else
  1219. throw new ArgumentException(Res.GetString(Res.XmlInternalError), "xmlMapping");
  1220. }
  1221. void GenerateInitCallbacksMethod() {
  1222. Writer.WriteLine();
  1223. Writer.WriteLine("protected override void InitCallbacks() {");
  1224. Writer.Indent++;
  1225. foreach (TypeScope scope in Scopes) {
  1226. foreach (TypeMapping typeMapping in scope.TypeMappings) {
  1227. if (typeMapping.IsSoap &&
  1228. (typeMapping is StructMapping || typeMapping is EnumMapping) &&
  1229. !typeMapping.TypeDesc.IsRoot) {
  1230. string methodName = (string)MethodNames[typeMapping];
  1231. Writer.Write("AddWriteCallback(");
  1232. Writer.Write(RaCodeGen.GetStringForTypeof(typeMapping.TypeDesc.CSharpName, typeMapping.TypeDesc.UseReflection));
  1233. Writer.Write(", ");
  1234. WriteQuotedCSharpString(typeMapping.TypeName);
  1235. Writer.Write(", ");
  1236. WriteQuotedCSharpString(typeMapping.Namespace);
  1237. Writer.Write(", new ");
  1238. Writer.Write(typeof(XmlSerializationWriteCallback).FullName);
  1239. Writer.Write("(this.");
  1240. Writer.Write(methodName);
  1241. Writer.WriteLine("));");
  1242. }
  1243. }
  1244. }
  1245. Writer.Indent--;
  1246. Writer.WriteLine("}");
  1247. }
  1248. void WriteQualifiedNameElement(string name, string ns, object defaultValue, string source, bool nullable, bool IsSoap, TypeMapping mapping) {
  1249. bool hasDefault = defaultValue != null && defaultValue != DBNull.Value;
  1250. if (hasDefault) {
  1251. WriteCheckDefault(source, defaultValue, nullable);
  1252. Writer.WriteLine(" {");
  1253. Writer.Indent++;
  1254. }
  1255. string suffix = IsSoap ? "Encoded" : "Literal";
  1256. Writer.Write(nullable ? ("WriteNullableQualifiedName" + suffix): "WriteElementQualifiedName");
  1257. Writer.Write("(");
  1258. WriteQuotedCSharpString(name);
  1259. if (ns != null) {
  1260. Writer.Write(", ");
  1261. WriteQuotedCSharpString(ns);
  1262. }
  1263. Writer.Write(", ");
  1264. Writer.Write(source);
  1265. if (IsSoap) {
  1266. Writer.Write(", new System.Xml.XmlQualifiedName(");
  1267. WriteQuotedCSharpString(mapping.TypeName);
  1268. Writer.Write(", ");
  1269. WriteQuotedCSharpString(mapping.Namespace);
  1270. Writer.Write(")");
  1271. }
  1272. Writer.WriteLine(");");
  1273. if (hasDefault) {
  1274. Writer.Indent--;
  1275. Writer.WriteLine("}");
  1276. }
  1277. }
  1278. void WriteEnumValue(EnumMapping mapping, string source) {
  1279. string methodName = ReferenceMapping(mapping);
  1280. #if DEBUG
  1281. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  1282. if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name) + Environment.StackTrace);
  1283. #endif
  1284. Writer.Write(methodName);
  1285. Writer.Write("(");
  1286. Writer.Write(source);
  1287. Writer.Write(")");
  1288. }
  1289. void WritePrimitiveValue(TypeDesc typeDesc, string source, bool isElement) {
  1290. if (typeDesc == StringTypeDesc || typeDesc.FormatterName == "String") {
  1291. Writer.Write(source);
  1292. }
  1293. else {
  1294. if (!typeDesc.HasCustomFormatter) {
  1295. Writer.Write(typeof(XmlConvert).FullName);
  1296. Writer.Write(".ToString((");
  1297. Writer.Write(typeDesc.CSharpName);
  1298. Writer.Write(")");
  1299. Writer.Write(source);
  1300. Writer.Write(")");
  1301. }
  1302. else {
  1303. Writer.Write("From");
  1304. Writer.Write(typeDesc.FormatterName);
  1305. Writer.Write("(");
  1306. Writer.Write(source);
  1307. Writer.Write(")");
  1308. }
  1309. }
  1310. }
  1311. void WritePrimitive(string method, string name, string ns, object defaultValue, string source, TypeMapping mapping, bool writeXsiType, bool isElement, bool isNullable) {
  1312. TypeDesc typeDesc = mapping.TypeDesc;
  1313. bool hasDefault = defaultValue != null && defaultValue != DBNull.Value && mapping.TypeDesc.HasDefaultSupport;
  1314. if (hasDefault) {
  1315. if (mapping is EnumMapping) {
  1316. #if DEBUG
  1317. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  1318. if (defaultValue.GetType() != typeof(string)) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, name + " has invalid default type " + defaultValue.GetType().Name));
  1319. #endif
  1320. Writer.Write("if (");
  1321. if (mapping.TypeDesc.UseReflection)
  1322. Writer.Write(RaCodeGen.GetStringForEnumLongValue(source, mapping.TypeDesc.UseReflection));
  1323. else
  1324. Writer.Write(source);
  1325. Writer.Write(" != ");
  1326. if (((EnumMapping)mapping).IsFlags) {
  1327. Writer.Write("(");
  1328. string[] values = ((string)defaultValue).Split(null);
  1329. for (int i = 0; i < values.Length; i++) {
  1330. if (values[i] == null || values[i].Length == 0)
  1331. continue;
  1332. if (i > 0)
  1333. Writer.WriteLine(" | ");
  1334. Writer.Write(RaCodeGen.GetStringForEnumCompare((EnumMapping)mapping, values[i], mapping.TypeDesc.UseReflection));
  1335. }
  1336. Writer.Write(")");
  1337. }
  1338. else {
  1339. Writer.Write(RaCodeGen.GetStringForEnumCompare((EnumMapping)mapping, (string)defaultValue, mapping.TypeDesc.UseReflection));
  1340. }
  1341. Writer.Write(")");
  1342. }
  1343. else {
  1344. WriteCheckDefault(source, defaultValue, isNullable);
  1345. }
  1346. Writer.WriteLine(" {");
  1347. Writer.Indent++;
  1348. }
  1349. Writer.Write(method);
  1350. Writer.Write("(");
  1351. WriteQuotedCSharpString(name);
  1352. if (ns != null) {
  1353. Writer.Write(", ");
  1354. WriteQuotedCSharpString(ns);
  1355. }
  1356. Writer.Write(", ");
  1357. if (mapping is EnumMapping) {
  1358. WriteEnumValue((EnumMapping)mapping, source);
  1359. }
  1360. else {
  1361. WritePrimitiveValue(typeDesc, source, isElement);
  1362. }
  1363. if (writeXsiType) {
  1364. Writer.Write(", new System.Xml.XmlQualifiedName(");
  1365. WriteQuotedCSharpString(mapping.TypeName);
  1366. Writer.Write(", ");
  1367. WriteQuotedCSharpString(mapping.Namespace);
  1368. Writer.Write(")");
  1369. }
  1370. Writer.WriteLine(");");
  1371. if (hasDefault) {
  1372. Writer.Indent--;
  1373. Writer.WriteLine("}");
  1374. }
  1375. }
  1376. void WriteTag(string methodName, string name, string ns) {
  1377. Writer.Write(methodName);
  1378. Writer.Write("(");
  1379. WriteQuotedCSharpString(name);
  1380. Writer.Write(", ");
  1381. if (ns == null) {
  1382. Writer.Write("null");
  1383. }
  1384. else {
  1385. WriteQuotedCSharpString(ns);
  1386. }
  1387. Writer.WriteLine(");");
  1388. }
  1389. void WriteTag(string methodName, string name, string ns, bool writePrefixed) {
  1390. Writer.Write(methodName);
  1391. Writer.Write("(");
  1392. WriteQuotedCSharpString(name);
  1393. Writer.Write(", ");
  1394. if (ns == null) {
  1395. Writer.Write("null");
  1396. }
  1397. else {
  1398. WriteQuotedCSharpString(ns);
  1399. }
  1400. Writer.Write(", null, ");
  1401. if (writePrefixed)
  1402. Writer.Write("true");
  1403. else
  1404. Writer.Write("false");
  1405. Writer.WriteLine(");");
  1406. }
  1407. void WriteStartElement(string name, string ns, bool writePrefixed) {
  1408. WriteTag("WriteStartElement", name, ns, writePrefixed);
  1409. }
  1410. void WriteEndElement() {
  1411. Writer.WriteLine("WriteEndElement();");
  1412. }
  1413. void WriteEndElement(string source) {
  1414. Writer.Write("WriteEndElement(");
  1415. Writer.Write(source);
  1416. Writer.WriteLine(");");
  1417. }
  1418. void WriteEncodedNullTag(string name, string ns) {
  1419. WriteTag("WriteNullTagEncoded", name, ns);
  1420. }
  1421. void WriteLiteralNullTag(string name, string ns) {
  1422. WriteTag("WriteNullTagLiteral", name, ns);
  1423. }
  1424. void WriteEmptyTag(string name, string ns) {
  1425. WriteTag("WriteEmptyTag", name, ns);
  1426. }
  1427. string GenerateMembersElement(XmlMembersMapping xmlMembersMapping) {
  1428. ElementAccessor element = xmlMembersMapping.Accessor;
  1429. MembersMapping mapping = (MembersMapping)element.Mapping;
  1430. bool hasWrapperElement = mapping.HasWrapperElement;
  1431. bool writeAccessors = mapping.WriteAccessors;
  1432. bool isRpc = xmlMembersMapping.IsSoap && writeAccessors;
  1433. string methodName = NextMethodName(element.Name);
  1434. Writer.WriteLine();
  1435. Writer.Write("public void ");
  1436. Writer.Write(methodName);
  1437. Writer.WriteLine("(object[] p) {");
  1438. Writer.Indent++;
  1439. Writer.WriteLine("WriteStartDocument();");
  1440. if (!mapping.IsSoap) {
  1441. Writer.WriteLine("TopLevelElement();");
  1442. }
  1443. // in the top-level method add check for the parameters length,
  1444. // because visual basic does not have a concept of an <out> parameter it uses <ByRef> instead
  1445. // so sometime we think that we have more parameters then supplied
  1446. Writer.WriteLine("int pLength = p.Length;");
  1447. if (hasWrapperElement) {
  1448. WriteStartElement(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""), mapping.IsSoap);
  1449. int xmlnsMember = FindXmlnsIndex(mapping.Members);
  1450. if (xmlnsMember >= 0) {
  1451. MemberMapping member = mapping.Members[xmlnsMember];
  1452. string source = "((" + typeof(XmlSerializerNamespaces).FullName + ")p[" + xmlnsMember.ToString(CultureInfo.InvariantCulture) + "])";
  1453. Writer.Write("if (pLength > ");
  1454. Writer.Write(xmlnsMember.ToString(CultureInfo.InvariantCulture));
  1455. Writer.WriteLine(") {");
  1456. Writer.Indent++;
  1457. WriteNamespaces(source);
  1458. Writer.Indent--;
  1459. Writer.WriteLine("}");
  1460. }
  1461. for (int i = 0; i < mapping.Members.Length; i++) {
  1462. MemberMapping member = mapping.Members[i];
  1463. if (member.Attribute != null && !member.Ignore) {
  1464. string source = "p[" + i.ToString(CultureInfo.InvariantCulture) + "]";
  1465. string specifiedSource = null;
  1466. int specifiedPosition = 0;
  1467. if (member.CheckSpecified != SpecifiedAccessor.None) {
  1468. string memberNameSpecified = member.Name + "Specified";
  1469. for (int j = 0; j < mapping.Members.Length; j++) {
  1470. if (mapping.Members[j].Name == memberNameSpecified) {
  1471. specifiedSource = "((bool) p[" + j.ToString(CultureInfo.InvariantCulture) + "])";
  1472. specifiedPosition = j;
  1473. break;
  1474. }
  1475. }
  1476. }
  1477. Writer.Write("if (pLength > ");
  1478. Writer.Write(i.ToString(CultureInfo.InvariantCulture));
  1479. Writer.WriteLine(") {");
  1480. Writer.Indent++;
  1481. if (specifiedSource != null) {
  1482. Writer.Write("if (pLength <= ");
  1483. Writer.Write(specifiedPosition.ToString(CultureInfo.InvariantCulture));
  1484. Writer.Write(" || ");
  1485. Writer.Write(specifiedSource);
  1486. Writer.WriteLine(") {");
  1487. Writer.Indent++;
  1488. }
  1489. WriteMember(source, member.Attribute, member.TypeDesc, "p");
  1490. if (specifiedSource != null) {
  1491. Writer.Indent--;
  1492. Writer.WriteLine("}");
  1493. }
  1494. Writer.Indent--;
  1495. Writer.WriteLine("}");
  1496. }
  1497. }
  1498. }
  1499. for (int i = 0; i < mapping.Members.Length; i++) {
  1500. MemberMapping member = mapping.Members[i];
  1501. if (member.Xmlns != null)
  1502. continue;
  1503. if (member.Ignore)
  1504. continue;
  1505. string specifiedSource = null;
  1506. int specifiedPosition = 0;
  1507. if (member.CheckSpecified != SpecifiedAccessor.None) {
  1508. string memberNameSpecified = member.Name + "Specified";
  1509. for (int j = 0; j < mapping.Members.Length; j++) {
  1510. if (mapping.Members[j].Name == memberNameSpecified) {
  1511. specifiedSource = "((bool) p[" + j.ToString(CultureInfo.InvariantCulture) + "])";
  1512. specifiedPosition = j;
  1513. break;
  1514. }
  1515. }
  1516. }
  1517. Writer.Write("if (pLength > ");
  1518. Writer.Write(i.ToString(CultureInfo.InvariantCulture));
  1519. Writer.WriteLine(") {");
  1520. Writer.Indent++;
  1521. if (specifiedSource != null) {
  1522. Writer.Write("if (pLength <= ");
  1523. Writer.Write(specifiedPosition.ToString(CultureInfo.InvariantCulture));
  1524. Writer.Write(" || ");
  1525. Writer.Write(specifiedSource);
  1526. Writer.WriteLine(") {");
  1527. Writer.Indent++;
  1528. }
  1529. string source = "p[" + i.ToString(CultureInfo.InvariantCulture) + "]";
  1530. string enumSource = null;
  1531. if (member.ChoiceIdentifier != null) {
  1532. for (int j = 0; j < mapping.Members.Length; j++) {
  1533. if (mapping.Members[j].Name == member.ChoiceIdentifier.MemberName) {
  1534. if (member.ChoiceIdentifier.Mapping.TypeDesc.UseReflection)
  1535. enumSource = "p[" + j.ToString(CultureInfo.InvariantCulture) + "]";
  1536. else
  1537. enumSource = "((" + mapping.Members[j].TypeDesc.CSharpName + ")p[" + j.ToString(CultureInfo.InvariantCulture) + "]" + ")";
  1538. break;
  1539. }
  1540. }
  1541. #if DEBUG
  1542. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  1543. if (enumSource == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Can not find " + member.ChoiceIdentifier.MemberName + " in the members mapping."));
  1544. #endif
  1545. }
  1546. if (isRpc && member.IsReturnValue && member.Elements.Length > 0) {
  1547. Writer.Write("WriteRpcResult(");
  1548. WriteQuotedCSharpString(member.Elements[0].Name);
  1549. Writer.Write(", ");
  1550. WriteQuotedCSharpString("");
  1551. Writer.WriteLine(");");
  1552. }
  1553. // override writeAccessors choice when we've written a wrapper element
  1554. WriteMember(source, enumSource, member.ElementsSortedByDerivation, member.Text, member.ChoiceIdentifier, member.TypeDesc, writeAccessors || hasWrapperElement);
  1555. if (specifiedSource != null) {
  1556. Writer.Indent--;
  1557. Writer.WriteLine("}");
  1558. }
  1559. Writer.Indent--;
  1560. Writer.WriteLine("}");
  1561. }
  1562. if (hasWrapperElement) {
  1563. WriteEndElement();
  1564. }
  1565. if (element.IsSoap) {
  1566. if (!hasWrapperElement && !writeAccessors) {
  1567. // doc/bare case -- allow extra members
  1568. Writer.Write("if (pLength > ");
  1569. Writer.Write(mapping.Members.Length.ToString(CultureInfo.InvariantCulture));
  1570. Writer.WriteLine(") {");
  1571. Writer.Indent++;
  1572. WriteExtraMembers(mapping.Members.Length.ToString(CultureInfo.InvariantCulture), "pLength");
  1573. Writer.Indent--;
  1574. Writer.WriteLine("}");
  1575. }
  1576. Writer.WriteLine("WriteReferencedElements();");
  1577. }
  1578. Writer.Indent--;
  1579. Writer.WriteLine("}");
  1580. return methodName;
  1581. }
  1582. string GenerateTypeElement(XmlTypeMapping xmlTypeMapping) {
  1583. ElementAccessor element = xmlTypeMapping.Accessor;
  1584. TypeMapping mapping = element.Mapping;
  1585. string methodName = NextMethodName(element.Name);
  1586. Writer.WriteLine();
  1587. Writer.Write("public void ");
  1588. Writer.Write(methodName);
  1589. Writer.WriteLine("(object o) {");
  1590. Writer.Indent++;
  1591. Writer.WriteLine("WriteStartDocument();");
  1592. Writer.WriteLine("if (o == null) {");
  1593. Writer.Indent++;
  1594. if (element.IsNullable){
  1595. if(mapping.IsSoap)
  1596. WriteEncodedNullTag(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""));
  1597. else
  1598. WriteLiteralNullTag(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""));
  1599. }
  1600. else
  1601. WriteEmptyTag(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""));
  1602. Writer.WriteLine("return;");
  1603. Writer.Indent--;
  1604. Writer.WriteLine("}");
  1605. if (!mapping.IsSoap && !mapping.TypeDesc.IsValueType && !mapping.TypeDesc.Type.IsPrimitive) {
  1606. Writer.WriteLine("TopLevelElement();");
  1607. }
  1608. WriteMember("o", null, new ElementAccessor[] { element }, null, null, mapping.TypeDesc, !element.IsSoap);
  1609. if (mapping.IsSoap) {
  1610. Writer.WriteLine("WriteReferencedElements();");
  1611. }
  1612. Writer.Indent--;
  1613. Writer.WriteLine("}");
  1614. return methodName;
  1615. }
  1616. string NextMethodName(string name) {
  1617. return "Write" + (++NextMethodNumber).ToString(null, NumberFormatInfo.InvariantInfo) + "_" + CodeIdentifier.MakeValidInternal(name);
  1618. }
  1619. void WriteEnumMethod(EnumMapping mapping) {
  1620. string methodName = (string)MethodNames[mapping];
  1621. Writer.WriteLine();
  1622. string fullTypeName = mapping.TypeDesc.CSharpName;
  1623. if (mapping.IsSoap) {
  1624. Writer.Write("void ");
  1625. Writer.Write(methodName);
  1626. Writer.WriteLine("(object e) {");
  1627. WriteLocalDecl(fullTypeName, "v", "e", mapping.TypeDesc.UseReflection);
  1628. }
  1629. else {
  1630. Writer.Write("string ");
  1631. Writer.Write(methodName);
  1632. Writer.Write("(");
  1633. Writer.Write(mapping.TypeDesc.UseReflection? "object" : fullTypeName );
  1634. Writer.WriteLine(" v) {");
  1635. }
  1636. Writer.Indent++;
  1637. Writer.WriteLine("string s = null;");
  1638. ConstantMapping[] constants = mapping.Constants;
  1639. if (constants.Length > 0) {
  1640. Hashtable values = new Hashtable();
  1641. if (mapping.TypeDesc.UseReflection)
  1642. Writer.WriteLine("switch ("+RaCodeGen.GetStringForEnumLongValue("v", mapping.TypeDesc.UseReflection)+" ){");
  1643. else
  1644. Writer.WriteLine("switch (v) {");
  1645. Writer.Indent++;
  1646. for (int i = 0; i < constants.Length; i++) {
  1647. ConstantMapping c = constants[i];
  1648. if (values[c.Value] == null) {
  1649. WriteEnumCase(fullTypeName, c, mapping.TypeDesc.UseReflection);
  1650. Writer.Write("s = ");
  1651. WriteQuotedCSharpString(c.XmlName);
  1652. Writer.WriteLine("; break;");
  1653. values.Add(c.Value, c.Value);
  1654. }
  1655. }
  1656. if (mapping.IsFlags) {
  1657. Writer.Write("default: s = FromEnum(");
  1658. Writer.Write(RaCodeGen.GetStringForEnumLongValue("v", mapping.TypeDesc.UseReflection));
  1659. Writer.Write(", new string[] {");
  1660. Writer.Indent++;
  1661. for (int i = 0; i < constants.Length; i++) {
  1662. ConstantMapping c = constants[i];
  1663. if (i > 0)
  1664. Writer.WriteLine(", ");
  1665. WriteQuotedCSharpString(c.XmlName);
  1666. }
  1667. Writer.Write("}, new ");
  1668. Writer.Write(typeof(long).FullName);
  1669. Writer.Write("[] {");
  1670. for (int i = 0; i < constants.Length; i++) {
  1671. ConstantMapping c = constants[i];
  1672. if (i > 0)
  1673. Writer.WriteLine(", ");
  1674. Writer.Write("(long)");
  1675. if (mapping.TypeDesc.UseReflection)
  1676. Writer.Write(c.Value.ToString(CultureInfo.InvariantCulture));
  1677. else {
  1678. Writer.Write(fullTypeName);
  1679. Writer.Write(".@");
  1680. CodeIdentifier.CheckValidIdentifier(c.Name);
  1681. Writer.Write(c.Name);
  1682. }
  1683. }
  1684. Writer.Indent--;
  1685. Writer.Write("}, ");
  1686. WriteQuotedCSharpString(mapping.TypeDesc.FullName);
  1687. Writer.WriteLine("); break;");
  1688. }
  1689. else {
  1690. Writer.Write("default: throw CreateInvalidEnumValueException(");
  1691. Writer.Write(RaCodeGen.GetStringForEnumLongValue("v", mapping.TypeDesc.UseReflection));
  1692. Writer.Write(".ToString(System.Globalization.CultureInfo.InvariantCulture), ");
  1693. WriteQuotedCSharpString(mapping.TypeDesc.FullName);
  1694. Writer.WriteLine(");");
  1695. }
  1696. Writer.Indent--;
  1697. Writer.WriteLine("}");
  1698. }
  1699. if (mapping.IsSoap) {
  1700. Writer.Write("WriteXsiType(");
  1701. WriteQuotedCSharpString(mapping.TypeName);
  1702. Writer.Write(", ");
  1703. WriteQuotedCSharpString(mapping.Namespace);
  1704. Writer.WriteLine(");");
  1705. Writer.WriteLine("Writer.WriteString(s);");
  1706. }
  1707. else {
  1708. Writer.WriteLine("return s;");
  1709. }
  1710. Writer.Indent--;
  1711. Writer.WriteLine("}");
  1712. }
  1713. void WriteDerivedTypes(StructMapping mapping) {
  1714. for (StructMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) {
  1715. string fullTypeName = derived.TypeDesc.CSharpName;
  1716. Writer.Write("else if (");
  1717. WriteTypeCompare("t", fullTypeName, derived.TypeDesc.UseReflection);
  1718. Writer.WriteLine(") {");
  1719. Writer.Indent++;
  1720. string methodName = ReferenceMapping(derived);
  1721. #if DEBUG
  1722. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  1723. if (methodName == null) throw new InvalidOperationException("deriaved from " + mapping.TypeDesc.FullName + ", " + Res.GetString(Res.XmlInternalErrorMethod, derived.TypeDesc.Name) + Environment.StackTrace);
  1724. #endif
  1725. Writer.Write(methodName);
  1726. Writer.Write("(n, ns,");
  1727. if(!derived.TypeDesc.UseReflection) Writer.Write("("+fullTypeName+")");
  1728. Writer.Write("o");
  1729. if (derived.TypeDesc.IsNullable)
  1730. Writer.Write(", isNullable");
  1731. Writer.Write(", true");
  1732. Writer.WriteLine(");");
  1733. Writer.WriteLine("return;");
  1734. Writer.Indent--;
  1735. Writer.WriteLine("}");
  1736. WriteDerivedTypes(derived);
  1737. }
  1738. }
  1739. void WriteEnumAndArrayTypes() {
  1740. foreach (TypeScope scope in Scopes) {
  1741. foreach (Mapping m in scope.TypeMappings) {
  1742. if (m is EnumMapping && !m.IsSoap) {
  1743. EnumMapping mapping = (EnumMapping)m;
  1744. string fullTypeName = mapping.TypeDesc.CSharpName;
  1745. Writer.Write("else if (");
  1746. WriteTypeCompare("t",fullTypeName, mapping.TypeDesc.UseReflection);
  1747. Writer.WriteLine(") {");
  1748. Writer.Indent++;
  1749. string methodName = ReferenceMapping(mapping);
  1750. #if DEBUG
  1751. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  1752. if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name) + Environment.StackTrace);
  1753. #endif
  1754. Writer.WriteLine("Writer.WriteStartElement(n, ns);");
  1755. Writer.Write("WriteXsiType(");
  1756. WriteQuotedCSharpString(mapping.TypeName);
  1757. Writer.Write(", ");
  1758. WriteQuotedCSharpString(mapping.Namespace);
  1759. Writer.WriteLine(");");
  1760. Writer.Write("Writer.WriteString(");
  1761. Writer.Write(methodName);
  1762. Writer.Write("(");
  1763. if (!mapping.TypeDesc.UseReflection) Writer.Write("("+fullTypeName+")");
  1764. Writer.WriteLine("o));");
  1765. Writer.WriteLine("Writer.WriteEndElement();");
  1766. Writer.WriteLine("return;");
  1767. Writer.Indent--;
  1768. Writer.WriteLine("}");
  1769. }
  1770. else if (m is ArrayMapping && !m.IsSoap) {
  1771. ArrayMapping mapping = m as ArrayMapping;
  1772. if (mapping == null || m.IsSoap) continue;
  1773. string fullTypeName = mapping.TypeDesc.CSharpName;
  1774. Writer.Write("else if (");
  1775. if (mapping.TypeDesc.IsArray)
  1776. WriteArrayTypeCompare("t", fullTypeName, mapping.TypeDesc.ArrayElementTypeDesc.CSharpName, mapping.TypeDesc.UseReflection);
  1777. else
  1778. WriteTypeCompare("t", fullTypeName, mapping.TypeDesc.UseReflection);
  1779. Writer.WriteLine(") {");
  1780. Writer.Indent++;
  1781. Writer.WriteLine("Writer.WriteStartElement(n, ns);");
  1782. Writer.Write("WriteXsiType(");
  1783. WriteQuotedCSharpString(mapping.TypeName);
  1784. Writer.Write(", ");
  1785. WriteQuotedCSharpString(mapping.Namespace);
  1786. Writer.WriteLine(");");
  1787. WriteMember("o", null, mapping.ElementsSortedByDerivation, null, null, mapping.TypeDesc, true);
  1788. Writer.WriteLine("Writer.WriteEndElement();");
  1789. Writer.WriteLine("return;");
  1790. Writer.Indent--;
  1791. Writer.WriteLine("}");
  1792. }
  1793. }
  1794. }
  1795. }
  1796. void WriteStructMethod(StructMapping mapping) {
  1797. if (mapping.IsSoap && mapping.TypeDesc.IsRoot) return;
  1798. string methodName = (string)MethodNames[mapping];
  1799. Writer.WriteLine();
  1800. Writer.Write("void ");
  1801. Writer.Write(methodName);
  1802. string fullTypeName = mapping.TypeDesc.CSharpName;
  1803. if (mapping.IsSoap) {
  1804. Writer.WriteLine("(object s) {");
  1805. Writer.Indent++;
  1806. WriteLocalDecl(fullTypeName, "o", "s", mapping.TypeDesc.UseReflection);
  1807. }
  1808. else {
  1809. Writer.Write("(string n, string ns, ");
  1810. Writer.Write(mapping.TypeDesc.UseReflection ? "object" : fullTypeName);
  1811. Writer.Write(" o");
  1812. if (mapping.TypeDesc.IsNullable)
  1813. Writer.Write(", bool isNullable");
  1814. Writer.WriteLine(", bool needType) {");
  1815. Writer.Indent++;
  1816. if (mapping.TypeDesc.IsNullable) {
  1817. Writer.WriteLine("if ((object)o == null) {");
  1818. Writer.Indent++;
  1819. Writer.WriteLine("if (isNullable) WriteNullTagLiteral(n, ns);");
  1820. Writer.WriteLine("return;");
  1821. Writer.Indent--;
  1822. Writer.WriteLine("}");
  1823. }
  1824. Writer.WriteLine("if (!needType) {");
  1825. Writer.Indent++;
  1826. Writer.Write(typeof(Type).FullName);
  1827. Writer.WriteLine(" t = o.GetType();");
  1828. Writer.Write("if (");
  1829. WriteTypeCompare("t", fullTypeName, mapping.TypeDesc.UseReflection);
  1830. Writer.WriteLine(") {");
  1831. Writer.WriteLine("}");
  1832. WriteDerivedTypes(mapping);
  1833. if (mapping.TypeDesc.IsRoot)
  1834. WriteEnumAndArrayTypes();
  1835. Writer.WriteLine("else {");
  1836. Writer.Indent++;
  1837. if (mapping.TypeDesc.IsRoot) {
  1838. Writer.WriteLine("WriteTypedPrimitive(n, ns, o, true);");
  1839. Writer.WriteLine("return;");
  1840. }
  1841. else {
  1842. Writer.WriteLine("throw CreateUnknownTypeException(o);");
  1843. }
  1844. Writer.Indent--;
  1845. Writer.WriteLine("}");
  1846. Writer.Indent--;
  1847. Writer.WriteLine("}");
  1848. }
  1849. if (!mapping.TypeDesc.IsAbstract) {
  1850. if (mapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(mapping.TypeDesc.Type)) {
  1851. Writer.WriteLine("EscapeName = false;");
  1852. }
  1853. string xmlnsSource = null;
  1854. MemberMapping[] members = TypeScope.GetAllMembers(mapping);
  1855. int xmlnsMember = FindXmlnsIndex(members);
  1856. if (xmlnsMember >= 0) {
  1857. MemberMapping member = members[xmlnsMember];
  1858. CodeIdentifier.CheckValidIdentifier(member.Name);
  1859. xmlnsSource = RaCodeGen.GetStringForMember("o", member.Name, mapping.TypeDesc);
  1860. if (mapping.TypeDesc.UseReflection) {
  1861. xmlnsSource = "(("+member.TypeDesc.CSharpName+")"+xmlnsSource+")";
  1862. }
  1863. }
  1864. if (!mapping.IsSoap) {
  1865. Writer.Write("WriteStartElement(n, ns, o, false, ");
  1866. if (xmlnsSource == null)
  1867. Writer.Write("null");
  1868. else
  1869. Writer.Write(xmlnsSource);
  1870. Writer.WriteLine(");");
  1871. if (!mapping.TypeDesc.IsRoot) {
  1872. Writer.Write("if (needType) WriteXsiType(");
  1873. WriteQuotedCSharpString(mapping.TypeName);
  1874. Writer.Write(", ");
  1875. WriteQuotedCSharpString(mapping.Namespace);
  1876. Writer.WriteLine(");");
  1877. }
  1878. }
  1879. else if (xmlnsSource != null) {
  1880. WriteNamespaces(xmlnsSource);
  1881. }
  1882. for (int i = 0; i < members.Length; i++) {
  1883. MemberMapping m = members[i];
  1884. if (m.Attribute != null) {
  1885. CodeIdentifier.CheckValidIdentifier(m.Name);
  1886. if (m.CheckShouldPersist) {
  1887. Writer.Write("if (");
  1888. string methodInvoke = RaCodeGen.GetStringForMethodInvoke("o", fullTypeName, "ShouldSerialize"+m.Name, mapping.TypeDesc.UseReflection);
  1889. if (mapping.TypeDesc.UseReflection) methodInvoke = "(("+typeof(bool).FullName+")"+methodInvoke+")";
  1890. Writer.Write(methodInvoke);
  1891. Writer.WriteLine(") {");
  1892. Writer.Indent++;
  1893. }
  1894. if (m.CheckSpecified != SpecifiedAccessor.None) {
  1895. Writer.Write("if (");
  1896. string memberGet = RaCodeGen.GetStringForMember("o", m.Name+"Specified", mapping.TypeDesc);
  1897. if(mapping.TypeDesc.UseReflection) memberGet = "(("+typeof(bool).FullName+")"+ memberGet+")";
  1898. Writer.Write(memberGet);
  1899. Writer.WriteLine(") {");
  1900. Writer.Indent++;
  1901. }
  1902. WriteMember(RaCodeGen.GetStringForMember("o", m.Name, mapping.TypeDesc), m.Attribute, m.TypeDesc, "o");
  1903. if (m.CheckSpecified != SpecifiedAccessor.None) {
  1904. Writer.Indent--;
  1905. Writer.WriteLine("}");
  1906. }
  1907. if (m.CheckShouldPersist) {
  1908. Writer.Indent--;
  1909. Writer.WriteLine("}");
  1910. }
  1911. }
  1912. }
  1913. for (int i = 0; i < members.Length; i++) {
  1914. MemberMapping m = members[i];
  1915. if (m.Xmlns != null)
  1916. continue;
  1917. CodeIdentifier.CheckValidIdentifier(m.Name);
  1918. bool checkShouldPersist = m.CheckShouldPersist && (m.Elements.Length > 0 || m.Text != null);
  1919. if (checkShouldPersist) {
  1920. Writer.Write("if (");
  1921. string methodInvoke = RaCodeGen.GetStringForMethodInvoke("o", fullTypeName, "ShouldSerialize"+m.Name, mapping.TypeDesc.UseReflection);
  1922. if (mapping.TypeDesc.UseReflection) methodInvoke = "(("+typeof(bool).FullName+")"+methodInvoke+")";
  1923. Writer.Write(methodInvoke);
  1924. Writer.WriteLine(") {");
  1925. Writer.Indent++;
  1926. }
  1927. if (m.CheckSpecified != SpecifiedAccessor.None) {
  1928. Writer.Write("if (");
  1929. string memberGet = RaCodeGen.GetStringForMember("o", m.Name+"Specified", mapping.TypeDesc);
  1930. if(mapping.TypeDesc.UseReflection) memberGet = "(("+typeof(bool).FullName+")"+ memberGet+")";
  1931. Writer.Write(memberGet);
  1932. Writer.WriteLine(") {");
  1933. Writer.Indent++;
  1934. }
  1935. string choiceSource = null;
  1936. if (m.ChoiceIdentifier != null){
  1937. CodeIdentifier.CheckValidIdentifier(m.ChoiceIdentifier.MemberName);
  1938. choiceSource = RaCodeGen.GetStringForMember("o", m.ChoiceIdentifier.MemberName, mapping.TypeDesc);
  1939. }
  1940. WriteMember(RaCodeGen.GetStringForMember("o", m.Name, mapping.TypeDesc), choiceSource, m.ElementsSortedByDerivation, m.Text, m.ChoiceIdentifier, m.TypeDesc, true);
  1941. if (m.CheckSpecified != SpecifiedAccessor.None) {
  1942. Writer.Indent--;
  1943. Writer.WriteLine("}");
  1944. }
  1945. if (checkShouldPersist) {
  1946. Writer.Indent--;
  1947. Writer.WriteLine("}");
  1948. }
  1949. }
  1950. if (!mapping.IsSoap) {
  1951. WriteEndElement("o");
  1952. }
  1953. }
  1954. Writer.Indent--;
  1955. Writer.WriteLine("}");
  1956. }
  1957. bool CanOptimizeWriteListSequence(TypeDesc listElementTypeDesc) {
  1958. // check to see if we can write values of the attribute sequentially
  1959. // currently we have only one data type (XmlQualifiedName) that we can not write "inline",
  1960. // because we need to output xmlns:qx="..." for each of the qnames
  1961. return (listElementTypeDesc != null && listElementTypeDesc != QnameTypeDesc);
  1962. }
  1963. void WriteMember(string source, AttributeAccessor attribute, TypeDesc memberTypeDesc, string parent) {
  1964. if (memberTypeDesc.IsAbstract) return;
  1965. if (memberTypeDesc.IsArrayLike) {
  1966. Writer.WriteLine("{");
  1967. Writer.Indent++;
  1968. string fullTypeName = memberTypeDesc.CSharpName;
  1969. WriteArrayLocalDecl(fullTypeName, "a", source, memberTypeDesc);
  1970. if (memberTypeDesc.IsNullable) {
  1971. Writer.WriteLine("if (a != null) {");
  1972. Writer.Indent++;
  1973. }
  1974. if (attribute.IsList) {
  1975. if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc)) {
  1976. Writer.Write("Writer.WriteStartAttribute(null, ");
  1977. WriteQuotedCSharpString(attribute.Name);
  1978. Writer.Write(", ");
  1979. string ns = attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : String.Empty;
  1980. if (ns != null) {
  1981. WriteQuotedCSharpString(ns);
  1982. }
  1983. else {
  1984. Writer.Write("null");
  1985. }
  1986. Writer.WriteLine(");");
  1987. }
  1988. else {
  1989. Writer.Write(typeof(StringBuilder).FullName);
  1990. Writer.Write(" sb = new ");
  1991. Writer.Write(typeof(StringBuilder).FullName);
  1992. Writer.WriteLine("();");
  1993. }
  1994. }
  1995. TypeDesc arrayElementTypeDesc = memberTypeDesc.ArrayElementTypeDesc;
  1996. if (memberTypeDesc.IsEnumerable) {
  1997. Writer.Write(" e = ");
  1998. Writer.Write(typeof(IEnumerator).FullName);
  1999. if (memberTypeDesc.IsPrivateImplementation) {
  2000. Writer.Write("((");
  2001. Writer.Write(typeof(IEnumerable).FullName);
  2002. Writer.WriteLine(").GetEnumerator();");
  2003. }
  2004. else if(memberTypeDesc.IsGenericInterface) {
  2005. if (memberTypeDesc.UseReflection) {
  2006. // we use wildcard method name for generic GetEnumerator method, so we cannot use GetStringForMethodInvoke call here
  2007. Writer.Write("(");
  2008. Writer.Write(typeof(IEnumerator).FullName);
  2009. Writer.Write(")");
  2010. Writer.Write(RaCodeGen.GetReflectionVariable(memberTypeDesc.CSharpName, "System.Collections.Generic.IEnumerable*"));
  2011. Writer.WriteLine(".Invoke(a, new object[0]);");
  2012. }
  2013. else {
  2014. Writer.Write("((System.Collections.Generic.IEnumerable<");
  2015. Writer.Write(arrayElementTypeDesc.CSharpName);
  2016. Writer.WriteLine(">)a).GetEnumerator();");
  2017. }
  2018. }
  2019. else {
  2020. if (memberTypeDesc.UseReflection) {
  2021. Writer.Write("(");
  2022. Writer.Write(typeof(IEnumerator).FullName);
  2023. Writer.Write(")");
  2024. }
  2025. Writer.Write(RaCodeGen.GetStringForMethodInvoke("a", memberTypeDesc.CSharpName, "GetEnumerator", memberTypeDesc.UseReflection));
  2026. Writer.WriteLine(";");
  2027. }
  2028. Writer.WriteLine("if (e != null)");
  2029. Writer.WriteLine("while (e.MoveNext()) {");
  2030. Writer.Indent++;
  2031. string arrayTypeFullName = arrayElementTypeDesc.CSharpName;
  2032. WriteLocalDecl(arrayTypeFullName, "ai", "e.Current", arrayElementTypeDesc.UseReflection);
  2033. }
  2034. else {
  2035. Writer.Write("for (int i = 0; i < ");
  2036. if (memberTypeDesc.IsArray) {
  2037. Writer.WriteLine("a.Length; i++) {");
  2038. }
  2039. else {
  2040. Writer.Write("((");
  2041. Writer.Write(typeof(ICollection).FullName);
  2042. Writer.WriteLine(")a).Count; i++) {");
  2043. }
  2044. Writer.Indent++;
  2045. string arrayTypeFullName = arrayElementTypeDesc.CSharpName;
  2046. WriteLocalDecl(arrayTypeFullName, "ai", RaCodeGen.GetStringForArrayMember("a", "i", memberTypeDesc), arrayElementTypeDesc.UseReflection);
  2047. }
  2048. if (attribute.IsList) {
  2049. // check to see if we can write values of the attribute sequentially
  2050. if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc)) {
  2051. Writer.WriteLine("if (i != 0) Writer.WriteString(\" \");");
  2052. Writer.Write("WriteValue(");
  2053. }
  2054. else {
  2055. Writer.WriteLine("if (i != 0) sb.Append(\" \");");
  2056. Writer.Write("sb.Append(");
  2057. }
  2058. if (attribute.Mapping is EnumMapping)
  2059. WriteEnumValue((EnumMapping)attribute.Mapping, "ai");
  2060. else
  2061. WritePrimitiveValue(arrayElementTypeDesc, "ai", true);
  2062. Writer.WriteLine(");");
  2063. }
  2064. else {
  2065. WriteAttribute("ai", attribute, parent);
  2066. }
  2067. Writer.Indent--;
  2068. Writer.WriteLine("}");
  2069. if (attribute.IsList) {
  2070. // check to see if we can write values of the attribute sequentially
  2071. if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc)) {
  2072. Writer.WriteLine("Writer.WriteEndAttribute();");
  2073. }
  2074. else {
  2075. Writer.WriteLine("if (sb.Length != 0) {");
  2076. Writer.Indent++;
  2077. Writer.Write("WriteAttribute(");
  2078. WriteQuotedCSharpString(attribute.Name);
  2079. Writer.Write(", ");
  2080. string ns = attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : String.Empty;
  2081. if (ns != null) {
  2082. WriteQuotedCSharpString(ns);
  2083. Writer.Write(", ");
  2084. }
  2085. Writer.WriteLine("sb.ToString());");
  2086. Writer.Indent--;
  2087. Writer.WriteLine("}");
  2088. }
  2089. }
  2090. if (memberTypeDesc.IsNullable) {
  2091. Writer.Indent--;
  2092. Writer.WriteLine("}");
  2093. }
  2094. Writer.Indent--;
  2095. Writer.WriteLine("}");
  2096. }
  2097. else {
  2098. WriteAttribute(source, attribute, parent);
  2099. }
  2100. }
  2101. void WriteAttribute(string source, AttributeAccessor attribute, string parent) {
  2102. if (attribute.Mapping is SpecialMapping) {
  2103. SpecialMapping special = (SpecialMapping)attribute.Mapping;
  2104. if (special.TypeDesc.Kind == TypeKind.Attribute || special.TypeDesc.CanBeAttributeValue) {
  2105. Writer.Write("WriteXmlAttribute(");
  2106. Writer.Write(source);
  2107. Writer.Write(", ");
  2108. Writer.Write(parent);
  2109. Writer.WriteLine(");");
  2110. }
  2111. else
  2112. throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
  2113. }
  2114. else {
  2115. TypeDesc typeDesc = attribute.Mapping.TypeDesc;
  2116. if (!typeDesc.UseReflection) source = "(("+typeDesc.CSharpName+")"+source+")";
  2117. WritePrimitive("WriteAttribute", attribute.Name, attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : "", attribute.Default, source, attribute.Mapping, false, false, false);
  2118. }
  2119. }
  2120. void WriteMember(string source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc memberTypeDesc, bool writeAccessors) {
  2121. if (memberTypeDesc.IsArrayLike &&
  2122. !(elements.Length == 1 && elements[0].Mapping is ArrayMapping))
  2123. WriteArray(source, choiceSource, elements, text, choice, memberTypeDesc);
  2124. else
  2125. WriteElements(source, choiceSource, elements, text, choice, "a", writeAccessors, memberTypeDesc.IsNullable);
  2126. }
  2127. void WriteArray(string source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc) {
  2128. if (elements.Length == 0 && text == null) return;
  2129. Writer.WriteLine("{");
  2130. Writer.Indent++;
  2131. string arrayTypeName = arrayTypeDesc.CSharpName;
  2132. WriteArrayLocalDecl(arrayTypeName, "a", source, arrayTypeDesc);
  2133. if (arrayTypeDesc.IsNullable) {
  2134. Writer.WriteLine("if (a != null) {");
  2135. Writer.Indent++;
  2136. }
  2137. if (choice != null) {
  2138. bool choiceUseReflection = choice.Mapping.TypeDesc.UseReflection;
  2139. string choiceFullName = choice.Mapping.TypeDesc.CSharpName;
  2140. WriteArrayLocalDecl(choiceFullName+"[]", "c", choiceSource, choice.Mapping.TypeDesc);
  2141. // write check for the choice identifier array
  2142. Writer.WriteLine("if (c == null || c.Length < a.Length) {");
  2143. Writer.Indent++;
  2144. Writer.Write("throw CreateInvalidChoiceIdentifierValueException(");
  2145. WriteQuotedCSharpString(choice.Mapping.TypeDesc.FullName);
  2146. Writer.Write(", ");
  2147. WriteQuotedCSharpString(choice.MemberName);
  2148. Writer.Write(");");
  2149. Writer.Indent--;
  2150. Writer.WriteLine("}");
  2151. }
  2152. WriteArrayItems(elements, text, choice, arrayTypeDesc, "a", "c");
  2153. if (arrayTypeDesc.IsNullable) {
  2154. Writer.Indent--;
  2155. Writer.WriteLine("}");
  2156. }
  2157. Writer.Indent--;
  2158. Writer.WriteLine("}");
  2159. }
  2160. void WriteArrayItems(ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc, string arrayName, string choiceName) {
  2161. TypeDesc arrayElementTypeDesc = arrayTypeDesc.ArrayElementTypeDesc;
  2162. if (arrayTypeDesc.IsEnumerable) {
  2163. Writer.Write(typeof(IEnumerator).FullName);
  2164. Writer.Write(" e = ");
  2165. if (arrayTypeDesc.IsPrivateImplementation) {
  2166. Writer.Write("((");
  2167. Writer.Write(typeof(IEnumerable).FullName);
  2168. Writer.Write(")");
  2169. Writer.Write(arrayName);
  2170. Writer.WriteLine(").GetEnumerator();");
  2171. }
  2172. else if(arrayTypeDesc.IsGenericInterface) {
  2173. if (arrayTypeDesc.UseReflection) {
  2174. // we use wildcard method name for generic GetEnumerator method, so we cannot use GetStringForMethodInvoke call here
  2175. Writer.Write("(");
  2176. Writer.Write(typeof(IEnumerator).FullName);
  2177. Writer.Write(")");
  2178. Writer.Write(RaCodeGen.GetReflectionVariable(arrayTypeDesc.CSharpName, "System.Collections.Generic.IEnumerable*"));
  2179. Writer.Write(".Invoke(");
  2180. Writer.Write(arrayName);
  2181. Writer.WriteLine(", new object[0]);");
  2182. }
  2183. else {
  2184. Writer.Write("((System.Collections.Generic.IEnumerable<");
  2185. Writer.Write(arrayElementTypeDesc.CSharpName);
  2186. Writer.Write(">)");
  2187. Writer.Write(arrayName);
  2188. Writer.WriteLine(").GetEnumerator();");
  2189. }
  2190. }
  2191. else {
  2192. if (arrayTypeDesc.UseReflection) {
  2193. Writer.Write("(");
  2194. Writer.Write(typeof(IEnumerator).FullName);
  2195. Writer.Write(")");
  2196. }
  2197. Writer.Write(RaCodeGen.GetStringForMethodInvoke(arrayName, arrayTypeDesc.CSharpName, "GetEnumerator", arrayTypeDesc.UseReflection));
  2198. Writer.WriteLine(";");
  2199. }
  2200. Writer.WriteLine("if (e != null)");
  2201. Writer.WriteLine("while (e.MoveNext()) {");
  2202. Writer.Indent++;
  2203. string arrayTypeFullName = arrayElementTypeDesc.CSharpName;
  2204. WriteLocalDecl(arrayTypeFullName, arrayName+"i", "e.Current", arrayElementTypeDesc.UseReflection);
  2205. WriteElements(arrayName + "i", choiceName + "i", elements, text, choice, arrayName + "a", true, true);
  2206. }
  2207. else {
  2208. Writer.Write("for (int i");
  2209. Writer.Write(arrayName);
  2210. Writer.Write(" = 0; i");
  2211. Writer.Write(arrayName);
  2212. Writer.Write(" < ");
  2213. if (arrayTypeDesc.IsArray) {
  2214. Writer.Write(arrayName);
  2215. Writer.Write(".Length");
  2216. }
  2217. else {
  2218. Writer.Write("((");
  2219. Writer.Write(typeof(ICollection).FullName);
  2220. Writer.Write(")");
  2221. Writer.Write(arrayName);
  2222. Writer.Write(").Count");
  2223. }
  2224. Writer.Write("; i");
  2225. Writer.Write(arrayName);
  2226. Writer.WriteLine("++) {");
  2227. Writer.Indent++;
  2228. int count = elements.Length + (text == null ? 0 : 1);
  2229. if (count > 1) {
  2230. string arrayTypeFullName = arrayElementTypeDesc.CSharpName;
  2231. WriteLocalDecl(arrayTypeFullName, arrayName+"i", RaCodeGen.GetStringForArrayMember(arrayName, "i"+arrayName, arrayTypeDesc), arrayElementTypeDesc.UseReflection);
  2232. if (choice != null) {
  2233. string choiceFullName = choice.Mapping.TypeDesc.CSharpName;
  2234. WriteLocalDecl(choiceFullName, choiceName+"i", RaCodeGen.GetStringForArrayMember(choiceName, "i"+arrayName, choice.Mapping.TypeDesc), choice.Mapping.TypeDesc.UseReflection);
  2235. }
  2236. WriteElements(arrayName + "i", choiceName + "i", elements, text, choice, arrayName + "a", true, arrayElementTypeDesc.IsNullable);
  2237. }
  2238. else {
  2239. WriteElements(RaCodeGen.GetStringForArrayMember(arrayName , "i" + arrayName, arrayTypeDesc), elements, text, choice, arrayName + "a", true, arrayElementTypeDesc.IsNullable);
  2240. }
  2241. }
  2242. Writer.Indent--;
  2243. Writer.WriteLine("}");
  2244. }
  2245. void WriteElements(string source, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) {
  2246. WriteElements(source, null, elements, text, choice, arrayName, writeAccessors, isNullable);
  2247. }
  2248. void WriteElements(string source, string enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) {
  2249. if (elements.Length == 0 && text == null) return;
  2250. if (elements.Length == 1 && text == null) {
  2251. TypeDesc td = elements[0].IsUnbounded ? elements[0].Mapping.TypeDesc.CreateArrayTypeDesc() : elements[0].Mapping.TypeDesc;
  2252. if (!elements[0].Any && !elements[0].Mapping.TypeDesc.UseReflection && !elements[0].Mapping.TypeDesc.IsOptionalValue)
  2253. source = "(("+td.CSharpName+")"+ source+")";
  2254. WriteElement(source, elements[0], arrayName, writeAccessors);
  2255. }
  2256. else {
  2257. if (isNullable && choice == null) {
  2258. Writer.Write("if ((object)(");
  2259. Writer.Write(source);
  2260. Writer.Write(") != null)");
  2261. }
  2262. Writer.WriteLine("{");
  2263. Writer.Indent++;
  2264. int anyCount = 0;
  2265. ArrayList namedAnys = new ArrayList();
  2266. ElementAccessor unnamedAny = null; // can only have one
  2267. bool wroteFirstIf = false;
  2268. string enumTypeName = choice == null ? null : choice.Mapping.TypeDesc.FullName;
  2269. for (int i = 0; i < elements.Length; i++) {
  2270. ElementAccessor element = elements[i];
  2271. if (element.Any) {
  2272. anyCount++;
  2273. if (element.Name != null && element.Name.Length > 0)
  2274. namedAnys.Add(element);
  2275. else if (unnamedAny == null)
  2276. unnamedAny = element;
  2277. }
  2278. else if (choice != null) {
  2279. bool useReflection = element.Mapping.TypeDesc.UseReflection;
  2280. string fullTypeName = element.Mapping.TypeDesc.CSharpName;
  2281. bool enumUseReflection = choice.Mapping.TypeDesc.UseReflection;
  2282. string enumFullName = (enumUseReflection?"":enumTypeName + ".@") + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, enumUseReflection);
  2283. if (wroteFirstIf) Writer.Write("else ");
  2284. else wroteFirstIf = true;
  2285. Writer.Write("if (");
  2286. Writer.Write(enumUseReflection?RaCodeGen.GetStringForEnumLongValue(enumSource, enumUseReflection):enumSource);
  2287. Writer.Write(" == ");
  2288. Writer.Write(enumFullName);
  2289. if (isNullable && !element.IsNullable) {
  2290. Writer.Write(" && ((object)(");
  2291. Writer.Write(source);
  2292. Writer.Write(") != null)");
  2293. }
  2294. Writer.WriteLine(") {");
  2295. Writer.Indent++;
  2296. WriteChoiceTypeCheck(source, fullTypeName, useReflection, choice, enumFullName, element.Mapping.TypeDesc);
  2297. string castedSource = source;
  2298. if (!useReflection)
  2299. castedSource = "(("+fullTypeName+")"+ source+")";
  2300. WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors);
  2301. Writer.Indent--;
  2302. Writer.WriteLine("}");
  2303. }
  2304. else {
  2305. bool useReflection = element.Mapping.TypeDesc.UseReflection;
  2306. TypeDesc td = element.IsUnbounded ? element.Mapping.TypeDesc.CreateArrayTypeDesc() : element.Mapping.TypeDesc;
  2307. string fullTypeName = td.CSharpName;
  2308. if (wroteFirstIf) Writer.Write("else ");
  2309. else wroteFirstIf = true;
  2310. Writer.Write("if (");
  2311. WriteInstanceOf(source, fullTypeName, useReflection);
  2312. Writer.WriteLine(") {");
  2313. Writer.Indent++;
  2314. string castedSource = source;
  2315. if (!useReflection)
  2316. castedSource = "(("+fullTypeName+")"+ source+")";
  2317. WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors);
  2318. Writer.Indent--;
  2319. Writer.WriteLine("}");
  2320. }
  2321. }
  2322. if (anyCount > 0) {
  2323. if (elements.Length - anyCount > 0) Writer.Write("else ");
  2324. string fullTypeName = typeof(XmlElement).FullName;
  2325. Writer.Write("if (");
  2326. Writer.Write(source);
  2327. Writer.Write(" is ");
  2328. Writer.Write(fullTypeName);
  2329. Writer.WriteLine(") {");
  2330. Writer.Indent++;
  2331. Writer.Write(fullTypeName);
  2332. Writer.Write(" elem = (");
  2333. Writer.Write(fullTypeName);
  2334. Writer.Write(")");
  2335. Writer.Write(source);
  2336. Writer.WriteLine(";");
  2337. int c = 0;
  2338. foreach (ElementAccessor element in namedAnys) {
  2339. if (c++ > 0) Writer.Write("else ");
  2340. string enumFullName = null;
  2341. bool useReflection = element.Mapping.TypeDesc.UseReflection;
  2342. if (choice != null) {
  2343. bool enumUseReflection = choice.Mapping.TypeDesc.UseReflection;
  2344. enumFullName = (enumUseReflection?"":enumTypeName + ".@") + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, enumUseReflection);
  2345. Writer.Write("if (");
  2346. Writer.Write(enumUseReflection?RaCodeGen.GetStringForEnumLongValue(enumSource, enumUseReflection):enumSource);
  2347. Writer.Write(" == ");
  2348. Writer.Write(enumFullName);
  2349. if (isNullable && !element.IsNullable) {
  2350. Writer.Write(" && ((object)(");
  2351. Writer.Write(source);
  2352. Writer.Write(") != null)");
  2353. }
  2354. Writer.WriteLine(") {");
  2355. Writer.Indent++;
  2356. }
  2357. Writer.Write("if (elem.Name == ");
  2358. WriteQuotedCSharpString(element.Name);
  2359. Writer.Write(" && elem.NamespaceURI == ");
  2360. WriteQuotedCSharpString(element.Namespace);
  2361. Writer.WriteLine(") {");
  2362. Writer.Indent++;
  2363. WriteElement("elem", element, arrayName, writeAccessors);
  2364. if (choice != null) {
  2365. Writer.Indent--;
  2366. Writer.WriteLine("}");
  2367. Writer.WriteLine("else {");
  2368. Writer.Indent++;
  2369. Writer.WriteLine("// throw Value '{0}' of the choice identifier '{1}' does not match element '{2}' from namespace '{3}'.");
  2370. Writer.Write("throw CreateChoiceIdentifierValueException(");
  2371. WriteQuotedCSharpString(enumFullName);
  2372. Writer.Write(", ");
  2373. WriteQuotedCSharpString(choice.MemberName);
  2374. Writer.WriteLine(", elem.Name, elem.NamespaceURI);");
  2375. Writer.Indent--;
  2376. Writer.WriteLine("}");
  2377. }
  2378. Writer.Indent--;
  2379. Writer.WriteLine("}");
  2380. }
  2381. if (c > 0) {
  2382. Writer.WriteLine("else {");
  2383. Writer.Indent++;
  2384. }
  2385. if (unnamedAny != null) {
  2386. WriteElement("elem", unnamedAny, arrayName, writeAccessors);
  2387. }
  2388. else {
  2389. Writer.WriteLine("throw CreateUnknownAnyElementException(elem.Name, elem.NamespaceURI);");
  2390. }
  2391. if (c > 0) {
  2392. Writer.Indent--;
  2393. Writer.WriteLine("}");
  2394. }
  2395. Writer.Indent--;
  2396. Writer.WriteLine("}");
  2397. }
  2398. if (text != null) {
  2399. bool useReflection = text.Mapping.TypeDesc.UseReflection;
  2400. string fullTypeName = text.Mapping.TypeDesc.CSharpName;
  2401. if (elements.Length > 0) {
  2402. Writer.Write("else ");
  2403. Writer.Write("if (");
  2404. WriteInstanceOf(source, fullTypeName, useReflection);
  2405. Writer.WriteLine(") {");
  2406. Writer.Indent++;
  2407. string castedSource = source;
  2408. if (!useReflection)
  2409. castedSource = "(("+fullTypeName+")"+ source+")";
  2410. WriteText(castedSource, text);
  2411. Writer.Indent--;
  2412. Writer.WriteLine("}");
  2413. }
  2414. else {
  2415. string castedSource = source;
  2416. if (!useReflection)
  2417. castedSource = "(("+fullTypeName+")"+ source+")";
  2418. WriteText(castedSource, text);
  2419. }
  2420. }
  2421. if (elements.Length > 0) {
  2422. Writer.Write("else ");
  2423. if (isNullable) {
  2424. Writer.Write(" if ((object)(");
  2425. Writer.Write(source);
  2426. Writer.Write(") != null)");
  2427. }
  2428. Writer.WriteLine("{");
  2429. Writer.Indent++;
  2430. Writer.Write("throw CreateUnknownTypeException(");
  2431. Writer.Write(source);
  2432. Writer.WriteLine(");");
  2433. Writer.Indent--;
  2434. Writer.WriteLine("}");
  2435. }
  2436. Writer.Indent--;
  2437. Writer.WriteLine("}");
  2438. }
  2439. }
  2440. void WriteText(string source, TextAccessor text) {
  2441. if (text.Mapping is PrimitiveMapping) {
  2442. PrimitiveMapping mapping = (PrimitiveMapping)text.Mapping;
  2443. Writer.Write("WriteValue(");
  2444. if (text.Mapping is EnumMapping) {
  2445. WriteEnumValue((EnumMapping)text.Mapping, source);
  2446. }
  2447. else {
  2448. WritePrimitiveValue(mapping.TypeDesc, source, false);
  2449. }
  2450. Writer.WriteLine(");");
  2451. }
  2452. else if (text.Mapping is SpecialMapping) {
  2453. SpecialMapping mapping = (SpecialMapping)text.Mapping;
  2454. switch (mapping.TypeDesc.Kind) {
  2455. case TypeKind.Node:
  2456. Writer.Write(source);
  2457. Writer.WriteLine(".WriteTo(Writer);");
  2458. break;
  2459. default:
  2460. throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
  2461. }
  2462. }
  2463. }
  2464. void WriteElement(string source, ElementAccessor element, string arrayName, bool writeAccessor) {
  2465. string name = writeAccessor ? element.Name : element.Mapping.TypeName;
  2466. string ns = element.Any && element.Name.Length == 0 ? null : (element.Form == XmlSchemaForm.Qualified ? (writeAccessor ? element.Namespace : element.Mapping.Namespace) : "");
  2467. if (element.Mapping is NullableMapping) {
  2468. Writer.Write("if (");
  2469. Writer.Write(source);
  2470. Writer.WriteLine(" != null) {");
  2471. Writer.Indent++;
  2472. string fullTypeName = element.Mapping.TypeDesc.BaseTypeDesc.CSharpName;
  2473. string castedSource = source;
  2474. if (!element.Mapping.TypeDesc.BaseTypeDesc.UseReflection)
  2475. castedSource = "(("+fullTypeName+")"+ source+")";
  2476. ElementAccessor e = element.Clone();
  2477. e.Mapping = ((NullableMapping)element.Mapping).BaseMapping;
  2478. WriteElement(e.Any ? source : castedSource, e, arrayName, writeAccessor);
  2479. Writer.Indent--;
  2480. Writer.WriteLine("}");
  2481. if (element.IsNullable) {
  2482. Writer.WriteLine("else {");
  2483. Writer.Indent++;
  2484. WriteLiteralNullTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
  2485. Writer.Indent--;
  2486. Writer.WriteLine("}");
  2487. }
  2488. }
  2489. else if (element.Mapping is ArrayMapping) {
  2490. ArrayMapping mapping = (ArrayMapping)element.Mapping;
  2491. if (mapping.IsSoap) {
  2492. Writer.Write("WritePotentiallyReferencingElement(");
  2493. WriteQuotedCSharpString(name);
  2494. Writer.Write(", ");
  2495. WriteQuotedCSharpString(ns);
  2496. Writer.Write(", ");
  2497. Writer.Write(source);
  2498. if (!writeAccessor) {
  2499. Writer.Write(", ");
  2500. Writer.Write(RaCodeGen.GetStringForTypeof(mapping.TypeDesc.CSharpName, mapping.TypeDesc.UseReflection));
  2501. Writer.Write(", true, ");
  2502. }
  2503. else {
  2504. Writer.Write(", null, false, ");
  2505. }
  2506. WriteValue(element.IsNullable);
  2507. Writer.WriteLine(");");
  2508. }
  2509. else if (element.IsUnbounded) {
  2510. TypeDesc td = mapping.TypeDesc.CreateArrayTypeDesc();
  2511. string fullTypeName = td.CSharpName;
  2512. string elementArrayName = "el" + arrayName;
  2513. string arrayIndex = "c" + elementArrayName;
  2514. Writer.WriteLine("{");
  2515. Writer.Indent++;
  2516. WriteArrayLocalDecl(fullTypeName, elementArrayName, source, mapping.TypeDesc);
  2517. if (element.IsNullable) {
  2518. WriteNullCheckBegin(elementArrayName, element);
  2519. }
  2520. else {
  2521. if (mapping.TypeDesc.IsNullable) {
  2522. Writer.Write("if (");
  2523. Writer.Write(elementArrayName);
  2524. Writer.Write(" != null)");
  2525. }
  2526. Writer.WriteLine("{");
  2527. Writer.Indent++;
  2528. }
  2529. Writer.Write("for (int ");
  2530. Writer.Write(arrayIndex);
  2531. Writer.Write(" = 0; ");
  2532. Writer.Write(arrayIndex);
  2533. Writer.Write(" < ");
  2534. if (td.IsArray) {
  2535. Writer.Write(elementArrayName);
  2536. Writer.Write(".Length");
  2537. }
  2538. else {
  2539. Writer.Write("((");
  2540. Writer.Write(typeof(ICollection).FullName);
  2541. Writer.Write(")");
  2542. Writer.Write(elementArrayName);
  2543. Writer.Write(").Count");
  2544. }
  2545. Writer.Write("; ");
  2546. Writer.Write(arrayIndex);
  2547. Writer.WriteLine("++) {");
  2548. Writer.Indent++;
  2549. element.IsUnbounded = false;
  2550. WriteElement(elementArrayName + "[" + arrayIndex + "]", element, arrayName, writeAccessor);
  2551. element.IsUnbounded = true;
  2552. Writer.Indent--;
  2553. Writer.WriteLine("}");
  2554. Writer.Indent--;
  2555. Writer.WriteLine("}");
  2556. Writer.Indent--;
  2557. Writer.WriteLine("}");
  2558. }
  2559. else {
  2560. string fullTypeName = mapping.TypeDesc.CSharpName;
  2561. Writer.WriteLine("{");
  2562. Writer.Indent++;
  2563. WriteArrayLocalDecl(fullTypeName, arrayName, source, mapping.TypeDesc);
  2564. if (element.IsNullable) {
  2565. WriteNullCheckBegin(arrayName, element);
  2566. }
  2567. else {
  2568. if (mapping.TypeDesc.IsNullable) {
  2569. Writer.Write("if (");
  2570. Writer.Write(arrayName);
  2571. Writer.Write(" != null)");
  2572. }
  2573. Writer.WriteLine("{");
  2574. Writer.Indent++;
  2575. }
  2576. WriteStartElement(name, ns, false);
  2577. WriteArrayItems(mapping.ElementsSortedByDerivation, null, null, mapping.TypeDesc, arrayName, null);
  2578. WriteEndElement();
  2579. Writer.Indent--;
  2580. Writer.WriteLine("}");
  2581. Writer.Indent--;
  2582. Writer.WriteLine("}");
  2583. }
  2584. }
  2585. else if (element.Mapping is EnumMapping) {
  2586. if (element.Mapping.IsSoap) {
  2587. string methodName = (string)MethodNames[element.Mapping];
  2588. Writer.Write("Writer.WriteStartElement(");
  2589. WriteQuotedCSharpString(name);
  2590. Writer.Write(", ");
  2591. WriteQuotedCSharpString(ns);
  2592. Writer.WriteLine(");");
  2593. Writer.Write(methodName);
  2594. Writer.Write("(");
  2595. Writer.Write(source);
  2596. Writer.WriteLine(");");
  2597. WriteEndElement();
  2598. }
  2599. else {
  2600. WritePrimitive("WriteElementString", name, ns, element.Default, source, element.Mapping, false, true, element.IsNullable);
  2601. }
  2602. }
  2603. else if (element.Mapping is PrimitiveMapping) {
  2604. PrimitiveMapping mapping = (PrimitiveMapping)element.Mapping;
  2605. if (mapping.TypeDesc == QnameTypeDesc)
  2606. WriteQualifiedNameElement(name, ns, element.Default, source, element.IsNullable, mapping.IsSoap, mapping);
  2607. else {
  2608. string suffixNullable = mapping.IsSoap ? "Encoded" : "Literal";
  2609. string suffixRaw = mapping.TypeDesc.XmlEncodingNotRequired?"Raw":"";
  2610. WritePrimitive(element.IsNullable ? ("WriteNullableString" + suffixNullable + suffixRaw) : ("WriteElementString" + suffixRaw),
  2611. name, ns, element.Default, source, mapping, mapping.IsSoap, true, element.IsNullable);
  2612. }
  2613. }
  2614. else if (element.Mapping is StructMapping) {
  2615. StructMapping mapping = (StructMapping)element.Mapping;
  2616. if (mapping.IsSoap) {
  2617. Writer.Write("WritePotentiallyReferencingElement(");
  2618. WriteQuotedCSharpString(name);
  2619. Writer.Write(", ");
  2620. WriteQuotedCSharpString(ns);
  2621. Writer.Write(", ");
  2622. Writer.Write(source);
  2623. if (!writeAccessor) {
  2624. Writer.Write(", ");
  2625. Writer.Write(RaCodeGen.GetStringForTypeof(mapping.TypeDesc.CSharpName, mapping.TypeDesc.UseReflection));
  2626. Writer.Write(", true, ");
  2627. }
  2628. else {
  2629. Writer.Write(", null, false, ");
  2630. }
  2631. WriteValue(element.IsNullable);
  2632. }
  2633. else {
  2634. string methodName = ReferenceMapping(mapping);
  2635. #if DEBUG
  2636. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  2637. if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name) + Environment.StackTrace);
  2638. #endif
  2639. Writer.Write(methodName);
  2640. Writer.Write("(");
  2641. WriteQuotedCSharpString(name);
  2642. Writer.Write(", ");
  2643. if (ns == null)
  2644. Writer.Write("null");
  2645. else {
  2646. WriteQuotedCSharpString(ns);
  2647. }
  2648. Writer.Write(", ");
  2649. Writer.Write(source);
  2650. if (mapping.TypeDesc.IsNullable) {
  2651. Writer.Write(", ");
  2652. WriteValue(element.IsNullable);
  2653. }
  2654. Writer.Write(", false");
  2655. }
  2656. Writer.WriteLine(");");
  2657. }
  2658. else if (element.Mapping is SpecialMapping) {
  2659. SpecialMapping mapping = (SpecialMapping)element.Mapping;
  2660. bool useReflection = mapping.TypeDesc.UseReflection;
  2661. TypeDesc td = mapping.TypeDesc;
  2662. string fullTypeName = td.CSharpName;
  2663. if (element.Mapping is SerializableMapping) {
  2664. WriteElementCall("WriteSerializable", typeof(IXmlSerializable), source, name, ns, element.IsNullable, !element.Any);
  2665. }
  2666. else {
  2667. // XmlNode, XmlElement
  2668. Writer.Write("if ((");
  2669. Writer.Write(source);
  2670. Writer.Write(") is ");
  2671. Writer.Write(typeof(XmlNode).FullName);
  2672. Writer.Write(" || ");
  2673. Writer.Write(source);
  2674. Writer.Write(" == null");
  2675. Writer.WriteLine(") {");
  2676. Writer.Indent++;
  2677. WriteElementCall("WriteElementLiteral", typeof(XmlNode), source, name, ns, element.IsNullable, element.Any);
  2678. Writer.Indent--;
  2679. Writer.WriteLine("}");
  2680. Writer.WriteLine("else {");
  2681. Writer.Indent++;
  2682. Writer.Write("throw CreateInvalidAnyTypeException(");
  2683. Writer.Write(source);
  2684. Writer.WriteLine(");");
  2685. Writer.Indent--;
  2686. Writer.WriteLine("}");
  2687. }
  2688. }
  2689. else {
  2690. throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
  2691. }
  2692. }
  2693. void WriteElementCall(string func, Type cast, string source, string name, string ns, bool isNullable, bool isAny) {
  2694. Writer.Write(func);
  2695. Writer.Write("((");
  2696. Writer.Write(cast.FullName);
  2697. Writer.Write(")");
  2698. Writer.Write(source);
  2699. Writer.Write(", ");
  2700. WriteQuotedCSharpString(name);
  2701. Writer.Write(", ");
  2702. WriteQuotedCSharpString(ns);
  2703. Writer.Write(", ");
  2704. WriteValue(isNullable);
  2705. Writer.Write(", ");
  2706. WriteValue(isAny);
  2707. Writer.WriteLine(");");
  2708. }
  2709. void WriteCheckDefault(string source, object value, bool isNullable) {
  2710. Writer.Write("if (");
  2711. if (value is string && ((string)value).Length == 0) {
  2712. // special case for string compare
  2713. Writer.Write("(");
  2714. Writer.Write(source);
  2715. if (isNullable)
  2716. Writer.Write(" == null) || (");
  2717. else
  2718. Writer.Write(" != null) && (");
  2719. Writer.Write(source);
  2720. Writer.Write(".Length != 0)");
  2721. }
  2722. else {
  2723. Writer.Write(source);
  2724. Writer.Write(" != ");
  2725. WriteValue(value);
  2726. }
  2727. Writer.Write(")");
  2728. }
  2729. void WriteChoiceTypeCheck(string source, string fullTypeName, bool useReflection, ChoiceIdentifierAccessor choice, string enumName, TypeDesc typeDesc) {
  2730. Writer.Write("if (((object)");
  2731. Writer.Write(source);
  2732. Writer.Write(") != null && !(");
  2733. WriteInstanceOf(source, fullTypeName, useReflection);
  2734. Writer.Write(")) throw CreateMismatchChoiceException(");
  2735. WriteQuotedCSharpString(typeDesc.FullName);
  2736. Writer.Write(", ");
  2737. WriteQuotedCSharpString(choice.MemberName);
  2738. Writer.Write(", ");
  2739. WriteQuotedCSharpString(enumName);
  2740. Writer.WriteLine(");");
  2741. }
  2742. void WriteNullCheckBegin(string source, ElementAccessor element) {
  2743. Writer.Write("if ((object)(");
  2744. Writer.Write(source);
  2745. Writer.WriteLine(") == null) {");
  2746. Writer.Indent++;
  2747. WriteLiteralNullTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
  2748. Writer.Indent--;
  2749. Writer.WriteLine("}");
  2750. Writer.WriteLine("else {");
  2751. Writer.Indent++;
  2752. }
  2753. void WriteValue(object value) {
  2754. if (value == null) {
  2755. Writer.Write("null");
  2756. }
  2757. else {
  2758. Type type = value.GetType();
  2759. switch (Type.GetTypeCode(type)) {
  2760. case TypeCode.String:
  2761. {
  2762. string s = (string)value;
  2763. WriteQuotedCSharpString(s);
  2764. }
  2765. break;
  2766. case TypeCode.Char:
  2767. {
  2768. Writer.Write('\'');
  2769. char ch = (char)value;
  2770. if (ch == '\'')
  2771. Writer.Write("\'");
  2772. else
  2773. Writer.Write(ch);
  2774. Writer.Write('\'');
  2775. }
  2776. break;
  2777. case TypeCode.Int32:
  2778. Writer.Write(((Int32)value).ToString(null, NumberFormatInfo.InvariantInfo));
  2779. break;
  2780. case TypeCode.Double:
  2781. Writer.Write(((Double)value).ToString("R", NumberFormatInfo.InvariantInfo));
  2782. break;
  2783. case TypeCode.Boolean:
  2784. Writer.Write((bool)value ? "true" : "false");
  2785. break;
  2786. case TypeCode.Int16:
  2787. case TypeCode.Int64:
  2788. case TypeCode.UInt16:
  2789. case TypeCode.UInt32:
  2790. case TypeCode.UInt64:
  2791. case TypeCode.Byte:
  2792. case TypeCode.SByte:
  2793. Writer.Write("(");
  2794. Writer.Write(type.FullName);
  2795. Writer.Write(")");
  2796. Writer.Write("(");
  2797. Writer.Write(Convert.ToString(value, NumberFormatInfo.InvariantInfo));
  2798. Writer.Write(")");
  2799. break;
  2800. case TypeCode.Single:
  2801. Writer.Write(((Single)value).ToString("R", NumberFormatInfo.InvariantInfo));
  2802. Writer.Write("f");
  2803. break;
  2804. case TypeCode.Decimal:
  2805. Writer.Write(((Decimal)value).ToString(null, NumberFormatInfo.InvariantInfo));
  2806. Writer.Write("m");
  2807. break;
  2808. case TypeCode.DateTime:
  2809. Writer.Write(" new ");
  2810. Writer.Write(type.FullName);
  2811. Writer.Write("(");
  2812. Writer.Write(((DateTime)value).Ticks.ToString(CultureInfo.InvariantCulture));
  2813. Writer.Write(")");
  2814. break;
  2815. default:
  2816. if (type.IsEnum) {
  2817. Writer.Write(((int)value).ToString(null, NumberFormatInfo.InvariantInfo));
  2818. }
  2819. else if(type == typeof(TimeSpan) && LocalAppContextSwitches.EnableTimeSpanSerialization) {
  2820. Writer.Write(" new ");
  2821. Writer.Write(type.FullName);
  2822. Writer.Write("(");
  2823. Writer.Write(((TimeSpan)value).Ticks.ToString(CultureInfo.InvariantCulture));
  2824. Writer.Write(")");
  2825. }
  2826. else {
  2827. throw new InvalidOperationException(Res.GetString(Res.XmlUnsupportedDefaultType, type.FullName));
  2828. }
  2829. break;
  2830. }
  2831. }
  2832. }
  2833. void WriteNamespaces(string source) {
  2834. Writer.Write("WriteNamespaceDeclarations(");
  2835. Writer.Write(source);
  2836. Writer.WriteLine(");");
  2837. }
  2838. int FindXmlnsIndex(MemberMapping[] members) {
  2839. for (int i = 0; i < members.Length; i++) {
  2840. if (members[i].Xmlns == null)
  2841. continue;
  2842. return i;
  2843. }
  2844. return -1;
  2845. }
  2846. void WriteExtraMembers(string loopStartSource, string loopEndSource) {
  2847. Writer.Write("for (int i = ");
  2848. Writer.Write(loopStartSource);
  2849. Writer.Write("; i < ");
  2850. Writer.Write(loopEndSource);
  2851. Writer.WriteLine("; i++) {");
  2852. Writer.Indent++;
  2853. Writer.WriteLine("if (p[i] != null) {");
  2854. Writer.Indent++;
  2855. Writer.WriteLine("WritePotentiallyReferencingElement(null, null, p[i], p[i].GetType(), true, false);");
  2856. Writer.Indent--;
  2857. Writer.WriteLine("}");
  2858. Writer.Indent--;
  2859. Writer.WriteLine("}");
  2860. }
  2861. void WriteLocalDecl(string typeName, string variableName, string initValue, bool useReflection) {
  2862. RaCodeGen.WriteLocalDecl(typeName, variableName, initValue, useReflection);
  2863. }
  2864. void WriteArrayLocalDecl(string typeName, string variableName, string initValue, TypeDesc arrayTypeDesc) {
  2865. RaCodeGen.WriteArrayLocalDecl(typeName, variableName, initValue, arrayTypeDesc);
  2866. }
  2867. void WriteTypeCompare(string variable, string escapedTypeName, bool useReflection){
  2868. RaCodeGen.WriteTypeCompare(variable, escapedTypeName, useReflection);
  2869. }
  2870. void WriteInstanceOf(string source, string escapedTypeName, bool useReflection){
  2871. RaCodeGen.WriteInstanceOf(source, escapedTypeName, useReflection);
  2872. }
  2873. void WriteArrayTypeCompare(string variable, string escapedTypeName, string elementTypeName, bool useReflection){
  2874. RaCodeGen.WriteArrayTypeCompare(variable, escapedTypeName, elementTypeName, useReflection);
  2875. }
  2876. void WriteEnumCase(string fullTypeName, ConstantMapping c, bool useReflection){
  2877. RaCodeGen.WriteEnumCase(fullTypeName, c, useReflection);
  2878. }
  2879. string FindChoiceEnumValue(ElementAccessor element, EnumMapping choiceMapping, bool useReflection) {
  2880. string enumValue = null;
  2881. for (int i = 0; i < choiceMapping.Constants.Length; i++) {
  2882. string xmlName = choiceMapping.Constants[i].XmlName;
  2883. if (element.Any && element.Name.Length == 0) {
  2884. if (xmlName == "##any:") {
  2885. if (useReflection)
  2886. enumValue = choiceMapping.Constants[i].Value.ToString(CultureInfo.InvariantCulture);
  2887. else
  2888. enumValue = choiceMapping.Constants[i].Name;
  2889. break;
  2890. }
  2891. continue;
  2892. }
  2893. int colon = xmlName.LastIndexOf(':');
  2894. string choiceNs = colon < 0 ? choiceMapping.Namespace : xmlName.Substring(0, colon);
  2895. string choiceName = colon < 0 ? xmlName : xmlName.Substring(colon+1);
  2896. if (element.Name == choiceName) {
  2897. if ((element.Form == XmlSchemaForm.Unqualified && string.IsNullOrEmpty(choiceNs)) || element.Namespace == choiceNs) {
  2898. if (useReflection)
  2899. enumValue = choiceMapping.Constants[i].Value.ToString(CultureInfo.InvariantCulture);
  2900. else
  2901. enumValue = choiceMapping.Constants[i].Name;
  2902. break;
  2903. }
  2904. }
  2905. }
  2906. if (enumValue == null || enumValue.Length == 0) {
  2907. if (element.Any && element.Name.Length == 0) {
  2908. // Type {0} is missing enumeration value '##any' for XmlAnyElementAttribute.
  2909. throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingAnyValue, choiceMapping.TypeDesc.FullName));
  2910. }
  2911. // Type {0} is missing value for '{1}'.
  2912. throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingValue, choiceMapping.TypeDesc.FullName, element.Namespace + ":" + element.Name, element.Name, element.Namespace));
  2913. }
  2914. if(!useReflection)
  2915. CodeIdentifier.CheckValidIdentifier(enumValue);
  2916. return enumValue;
  2917. }
  2918. }
  2919. internal static class DynamicAssemblies {
  2920. static ArrayList assembliesInConfig = new ArrayList();
  2921. static volatile Hashtable nameToAssemblyMap = new Hashtable();
  2922. static volatile Hashtable assemblyToNameMap = new Hashtable();
  2923. static Hashtable tableIsTypeDynamic = Hashtable.Synchronized(new Hashtable());
  2924. static volatile FileIOPermission fileIOPermission;
  2925. static FileIOPermission UnrestrictedFileIOPermission {
  2926. get {
  2927. if (fileIOPermission == null) {
  2928. fileIOPermission = new FileIOPermission(PermissionState.Unrestricted);
  2929. }
  2930. return fileIOPermission;
  2931. }
  2932. }
  2933. // SxS: This method does not take any resource name and does not expose any resources to the caller.
  2934. // It's OK to suppress the SxS warning.
  2935. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  2936. [ResourceExposure(ResourceScope.None)]
  2937. internal static bool IsTypeDynamic(Type type) {
  2938. object oIsTypeDynamic = tableIsTypeDynamic[type];
  2939. if (oIsTypeDynamic == null) {
  2940. UnrestrictedFileIOPermission.Assert();
  2941. Assembly assembly = type.Assembly;
  2942. bool isTypeDynamic = assembly.IsDynamic || string.IsNullOrEmpty(assembly.Location);
  2943. if (!isTypeDynamic)
  2944. {
  2945. if (type.IsArray)
  2946. {
  2947. isTypeDynamic = IsTypeDynamic(type.GetElementType());
  2948. }
  2949. else if (type.IsGenericType)
  2950. {
  2951. Type[] parameterTypes = type.GetGenericArguments();
  2952. if (parameterTypes != null)
  2953. {
  2954. for (int i = 0; i < parameterTypes.Length; i++)
  2955. {
  2956. Type parameterType = parameterTypes[i];
  2957. if (!(parameterType == null || parameterType.IsGenericParameter))
  2958. {
  2959. isTypeDynamic = IsTypeDynamic(parameterType);
  2960. if (isTypeDynamic)
  2961. break;
  2962. }
  2963. }
  2964. }
  2965. }
  2966. }
  2967. tableIsTypeDynamic[type] = oIsTypeDynamic = isTypeDynamic;
  2968. }
  2969. return (bool)oIsTypeDynamic;
  2970. }
  2971. internal static bool IsTypeDynamic(Type[] arguments) {
  2972. foreach (Type t in arguments){
  2973. if (DynamicAssemblies.IsTypeDynamic(t)) {
  2974. return true;
  2975. }
  2976. }
  2977. return false;
  2978. }
  2979. internal static void Add(Assembly a) {
  2980. lock (nameToAssemblyMap) {
  2981. if (assemblyToNameMap[a] != null) {
  2982. //already added
  2983. return;
  2984. }
  2985. Assembly oldAssembly = nameToAssemblyMap[a.FullName] as Assembly;
  2986. string key = null;
  2987. if (oldAssembly == null) {
  2988. key = a.FullName;
  2989. }
  2990. else if(oldAssembly != a) {
  2991. //more than one assembly with same name
  2992. key = a.FullName+", "+nameToAssemblyMap.Count;
  2993. }
  2994. if (key != null) {
  2995. nameToAssemblyMap.Add(key, a);
  2996. assemblyToNameMap.Add(a, key);
  2997. }
  2998. }
  2999. }
  3000. internal static Assembly Get(string fullName){
  3001. return nameToAssemblyMap!=null?(Assembly)nameToAssemblyMap[fullName]:null;
  3002. }
  3003. internal static string GetName(Assembly a){
  3004. return assemblyToNameMap!=null?(string)assemblyToNameMap[a]:null;
  3005. }
  3006. }
  3007. internal class ReflectionAwareCodeGen {
  3008. private const string hexDigits = "0123456789ABCDEF";
  3009. const string arrayMemberKey = "0";
  3010. // reflectionVariables holds mapping between a reflection entity
  3011. // referenced in the generated code (such as TypeInfo,
  3012. // FieldInfo) and the variable which represent the entity (and
  3013. // initialized before).
  3014. // The types of reflection entity and corresponding key is
  3015. // given below.
  3016. // ----------------------------------------------------------------------------------
  3017. // Entity Key
  3018. // ----------------------------------------------------------------------------------
  3019. // Assembly assembly.FullName
  3020. // Type CodeIdentifier.EscapedKeywords(type.FullName)
  3021. // Field fieldName+":"+CodeIdentifier.EscapedKeywords(containingType.FullName>)
  3022. // Property propertyName+":"+CodeIdentifier.EscapedKeywords(containingType.FullName)
  3023. // ArrayAccessor "0:"+CodeIdentifier.EscapedKeywords(typeof(Array).FullName)
  3024. // MyCollectionAccessor "0:"+CodeIdentifier.EscapedKeywords(typeof(MyCollection).FullName)
  3025. // ----------------------------------------------------------------------------------
  3026. Hashtable reflectionVariables = null;
  3027. int nextReflectionVariableNumber = 0;
  3028. IndentedWriter writer;
  3029. internal ReflectionAwareCodeGen(IndentedWriter writer){
  3030. this.writer = writer;
  3031. }
  3032. internal void WriteReflectionInit(TypeScope scope){
  3033. foreach (Type type in scope.Types) {
  3034. TypeDesc typeDesc = scope.GetTypeDesc(type);
  3035. if (typeDesc.UseReflection)
  3036. WriteTypeInfo(scope, typeDesc, type);
  3037. }
  3038. }
  3039. string WriteTypeInfo(TypeScope scope, TypeDesc typeDesc, Type type){
  3040. InitTheFirstTime();
  3041. string typeFullName = typeDesc.CSharpName;
  3042. string typeVariable = (string)reflectionVariables[typeFullName];
  3043. if (typeVariable != null)
  3044. return typeVariable;
  3045. if (type.IsArray)
  3046. {
  3047. typeVariable = GenerateVariableName("array", typeDesc.CSharpName);
  3048. TypeDesc elementTypeDesc = typeDesc.ArrayElementTypeDesc;
  3049. if (elementTypeDesc.UseReflection)
  3050. {
  3051. string elementTypeVariable = WriteTypeInfo(scope, elementTypeDesc, scope.GetTypeFromTypeDesc(elementTypeDesc));
  3052. writer.WriteLine("static "+typeof(Type).FullName+" "+typeVariable +" = " + elementTypeVariable + ".MakeArrayType();");
  3053. }
  3054. else
  3055. {
  3056. string assemblyVariable = WriteAssemblyInfo(type);
  3057. writer.Write("static "+typeof(Type).FullName+" "+typeVariable +" = "+assemblyVariable+".GetType(");
  3058. WriteQuotedCSharpString(type.FullName);
  3059. writer.WriteLine(");");
  3060. }
  3061. }
  3062. else
  3063. {
  3064. typeVariable = GenerateVariableName("type", typeDesc.CSharpName);
  3065. Type parameterType = Nullable.GetUnderlyingType(type);
  3066. if (parameterType != null)
  3067. {
  3068. string parameterTypeVariable = WriteTypeInfo(scope, scope.GetTypeDesc(parameterType), parameterType);
  3069. writer.WriteLine("static "+typeof(Type).FullName+" "+typeVariable +" = typeof(System.Nullable<>).MakeGenericType(new " + typeof(Type).FullName + "[] {"+parameterTypeVariable+"});");
  3070. }
  3071. else
  3072. {
  3073. string assemblyVariable = WriteAssemblyInfo(type);
  3074. writer.Write("static "+typeof(Type).FullName+" "+typeVariable +" = "+assemblyVariable+".GetType(");
  3075. WriteQuotedCSharpString(type.FullName);
  3076. writer.WriteLine(");");
  3077. }
  3078. }
  3079. reflectionVariables.Add(typeFullName, typeVariable);
  3080. TypeMapping mapping = scope.GetTypeMappingFromTypeDesc(typeDesc);
  3081. if (mapping != null)
  3082. WriteMappingInfo(mapping, typeVariable, type);
  3083. if (typeDesc.IsCollection || typeDesc.IsEnumerable){// Arrays use the generic item_Array
  3084. TypeDesc elementTypeDesc = typeDesc.ArrayElementTypeDesc;
  3085. if (elementTypeDesc.UseReflection)
  3086. WriteTypeInfo(scope, elementTypeDesc, scope.GetTypeFromTypeDesc(elementTypeDesc));
  3087. WriteCollectionInfo(typeVariable, typeDesc, type);
  3088. }
  3089. return typeVariable;
  3090. }
  3091. void InitTheFirstTime(){
  3092. if (reflectionVariables == null){
  3093. reflectionVariables = new Hashtable();
  3094. writer.Write(String.Format(CultureInfo.InvariantCulture, helperClassesForUseReflection,
  3095. "object", "string", typeof(Type).FullName,
  3096. typeof(FieldInfo).FullName, typeof(PropertyInfo).FullName,
  3097. typeof(MemberInfo).FullName, typeof(MemberTypes).FullName));
  3098. WriteDefaultIndexerInit(typeof(IList), typeof(Array).FullName, false, false);
  3099. }
  3100. }
  3101. void WriteMappingInfo(TypeMapping mapping, string typeVariable, Type type){
  3102. string typeFullName = mapping.TypeDesc.CSharpName;
  3103. if(mapping is StructMapping){
  3104. StructMapping structMapping = mapping as StructMapping;
  3105. for (int i = 0; i < structMapping.Members.Length; i++) {
  3106. MemberMapping member = structMapping.Members[i];
  3107. string memberVariable = WriteMemberInfo(type, typeFullName, typeVariable, member.Name);
  3108. if (member.CheckShouldPersist){
  3109. string memberName = "ShouldSerialize"+member.Name;
  3110. memberVariable = WriteMethodInfo(typeFullName, typeVariable, memberName, false);
  3111. }
  3112. if (member.CheckSpecified != SpecifiedAccessor.None) {
  3113. string memberName = member.Name+"Specified";
  3114. memberVariable = WriteMemberInfo(type, typeFullName, typeVariable, memberName);
  3115. }
  3116. if (member.ChoiceIdentifier != null){
  3117. string memberName = member.ChoiceIdentifier.MemberName;
  3118. memberVariable = WriteMemberInfo(type, typeFullName, typeVariable, memberName);
  3119. }
  3120. }
  3121. }
  3122. else if (mapping is EnumMapping){
  3123. FieldInfo[] enumFields = type.GetFields();
  3124. for (int i = 0; i < enumFields.Length; i++) {
  3125. WriteMemberInfo(type, typeFullName, typeVariable, enumFields[i].Name);
  3126. }
  3127. }
  3128. }
  3129. void WriteCollectionInfo(string typeVariable, TypeDesc typeDesc, Type type){
  3130. string typeFullName = CodeIdentifier.GetCSharpName(type);
  3131. string elementTypeFullName = typeDesc.ArrayElementTypeDesc.CSharpName;
  3132. bool elementUseReflection = typeDesc.ArrayElementTypeDesc.UseReflection;
  3133. if (typeDesc.IsCollection) {
  3134. WriteDefaultIndexerInit(type, typeFullName, typeDesc.UseReflection, elementUseReflection);
  3135. }
  3136. else if (typeDesc.IsEnumerable) {
  3137. if (typeDesc.IsGenericInterface) {
  3138. WriteMethodInfo(typeFullName, typeVariable, "System.Collections.Generic.IEnumerable*", true);
  3139. }
  3140. else if (!typeDesc.IsPrivateImplementation) {
  3141. WriteMethodInfo(typeFullName, typeVariable, "GetEnumerator", true);
  3142. }
  3143. }
  3144. WriteMethodInfo(typeFullName, typeVariable, "Add", false, GetStringForTypeof(elementTypeFullName, elementUseReflection));
  3145. }
  3146. string WriteAssemblyInfo(Type type){
  3147. string assemblyFullName = type.Assembly.FullName;
  3148. string assemblyVariable = (string)reflectionVariables[assemblyFullName];
  3149. if ( assemblyVariable == null){
  3150. int iComma = assemblyFullName.IndexOf(',');
  3151. string assemblyName = (iComma>-1)?assemblyFullName.Substring(0, iComma):assemblyFullName;
  3152. assemblyVariable = GenerateVariableName("assembly", assemblyName);
  3153. //writer.WriteLine("static "+ typeof(Assembly).FullName+" "+assemblyVariable+" = "+typeof(Assembly).FullName+".Load(");
  3154. writer.Write("static "+ typeof(Assembly).FullName+" "+assemblyVariable+" = "+"ResolveDynamicAssembly(");
  3155. WriteQuotedCSharpString(DynamicAssemblies.GetName(type.Assembly)/*assemblyFullName*/);
  3156. writer.WriteLine(");");
  3157. reflectionVariables.Add(assemblyFullName, assemblyVariable);
  3158. }
  3159. return assemblyVariable;
  3160. }
  3161. string WriteMemberInfo(Type type, string escapedName, string typeVariable, string memberName){
  3162. MemberInfo[] memberInfos = type.GetMember(memberName);
  3163. for (int i = 0; i < memberInfos.Length; i++) {
  3164. MemberTypes memberType = memberInfos[i].MemberType;
  3165. if (memberType == MemberTypes.Property){
  3166. string propVariable = GenerateVariableName("prop", memberName);
  3167. writer.Write("static XSPropInfo "+propVariable+" = new XSPropInfo("+typeVariable+", ");
  3168. WriteQuotedCSharpString(memberName);
  3169. writer.WriteLine(");");
  3170. reflectionVariables.Add(memberName+":"+escapedName, propVariable);
  3171. return propVariable;
  3172. }
  3173. else if (memberType == MemberTypes.Field){
  3174. string fieldVariable = GenerateVariableName("field", memberName);
  3175. writer.Write("static XSFieldInfo "+fieldVariable+" = new XSFieldInfo("+typeVariable+", ");
  3176. WriteQuotedCSharpString(memberName);
  3177. writer.WriteLine(");");
  3178. reflectionVariables.Add(memberName+":"+escapedName, fieldVariable);
  3179. return fieldVariable;
  3180. }
  3181. }
  3182. throw new InvalidOperationException(Res.GetString(Res.XmlSerializerUnsupportedType, memberInfos[0].ToString()));
  3183. }
  3184. string WriteMethodInfo(string escapedName, string typeVariable, string memberName, bool isNonPublic, params string[] paramTypes){
  3185. string methodVariable = GenerateVariableName("method", memberName);
  3186. writer.Write("static "+typeof(MethodInfo).FullName+" "+methodVariable+" = "+typeVariable+".GetMethod(");
  3187. WriteQuotedCSharpString(memberName);
  3188. writer.Write(", ");
  3189. string bindingFlags = typeof(BindingFlags).FullName;
  3190. writer.Write(bindingFlags);
  3191. writer.Write(".Public | ");
  3192. writer.Write(bindingFlags);
  3193. writer.Write(".Instance | ");
  3194. writer.Write(bindingFlags);
  3195. writer.Write(".Static");
  3196. if (isNonPublic) {
  3197. writer.Write(" | ");
  3198. writer.Write(bindingFlags);
  3199. writer.Write(".NonPublic");
  3200. }
  3201. writer.Write(", null, ");
  3202. writer.Write("new "+typeof(Type).FullName+"[] { ");
  3203. for(int i=0;i<paramTypes.Length;i++){
  3204. writer.Write(paramTypes[i]);
  3205. if(i < (paramTypes.Length-1))
  3206. writer.Write(", ");
  3207. }
  3208. writer.WriteLine("}, null);");
  3209. reflectionVariables.Add(memberName+":"+escapedName, methodVariable);
  3210. return methodVariable;
  3211. }
  3212. string WriteDefaultIndexerInit(Type type, string escapedName, bool collectionUseReflection, bool elementUseReflection){
  3213. string itemVariable = GenerateVariableName("item", escapedName);
  3214. PropertyInfo defaultIndexer = TypeScope.GetDefaultIndexer(type, null);
  3215. writer.Write("static XSArrayInfo ");
  3216. writer.Write(itemVariable);
  3217. writer.Write("= new XSArrayInfo(");
  3218. writer.Write(GetStringForTypeof(CodeIdentifier.GetCSharpName(type), collectionUseReflection));
  3219. writer.Write(".GetProperty(");
  3220. WriteQuotedCSharpString(defaultIndexer.Name);
  3221. writer.Write(",");
  3222. //defaultIndexer.PropertyType is same as TypeDesc.ElementTypeDesc
  3223. writer.Write(GetStringForTypeof(CodeIdentifier.GetCSharpName(defaultIndexer.PropertyType), elementUseReflection));
  3224. writer.Write(",new ");
  3225. writer.Write(typeof(Type[]).FullName);
  3226. writer.WriteLine("{typeof(int)}));");
  3227. reflectionVariables.Add(arrayMemberKey+":" + escapedName, itemVariable);
  3228. return itemVariable;
  3229. }
  3230. private string GenerateVariableName(string prefix, string fullName){
  3231. ++nextReflectionVariableNumber;
  3232. return prefix+nextReflectionVariableNumber+"_"+
  3233. CodeIdentifier.MakeValidInternal(fullName.Replace('.','_'));
  3234. }
  3235. internal string GetReflectionVariable(string typeFullName, string memberName){
  3236. string key;
  3237. if(memberName == null)
  3238. key = typeFullName;
  3239. else
  3240. key = memberName+":"+typeFullName;
  3241. return (string)reflectionVariables[key];
  3242. }
  3243. internal string GetStringForMethodInvoke(string obj, string escapedTypeName, string methodName, bool useReflection, params string[] args){
  3244. StringBuilder sb = new StringBuilder();
  3245. if (useReflection){
  3246. sb.Append(GetReflectionVariable(escapedTypeName, methodName));
  3247. sb.Append(".Invoke(");
  3248. sb.Append(obj);
  3249. sb.Append(", new object[] {");
  3250. }
  3251. else{
  3252. sb.Append(obj);
  3253. sb.Append(".@");
  3254. sb.Append(methodName);
  3255. sb.Append("(");
  3256. }
  3257. for(int i=0;i<args.Length;i++){
  3258. if(i != 0)
  3259. sb.Append(", ");
  3260. sb.Append(args[i]);
  3261. }
  3262. if (useReflection)
  3263. sb.Append( "})");
  3264. else
  3265. sb.Append( ")");
  3266. return sb.ToString();
  3267. }
  3268. internal string GetStringForEnumCompare(EnumMapping mapping, string memberName, bool useReflection){
  3269. if(!useReflection){
  3270. CodeIdentifier.CheckValidIdentifier(memberName);
  3271. return mapping.TypeDesc.CSharpName+".@"+memberName;
  3272. }
  3273. string memberAccess = GetStringForEnumMember(mapping.TypeDesc.CSharpName, memberName, useReflection);
  3274. return GetStringForEnumLongValue(memberAccess, useReflection);
  3275. }
  3276. internal string GetStringForEnumLongValue(string variable, bool useReflection){
  3277. if (useReflection)
  3278. return typeof(Convert).FullName+".ToInt64("+variable+")";
  3279. return "(("+typeof(long).FullName+")"+variable+")";
  3280. }
  3281. internal string GetStringForTypeof(string typeFullName, bool useReflection){
  3282. if (useReflection){
  3283. return GetReflectionVariable(typeFullName, null);
  3284. }
  3285. else{
  3286. return "typeof("+typeFullName+")";
  3287. }
  3288. }
  3289. internal string GetStringForMember(string obj, string memberName, TypeDesc typeDesc){
  3290. if (!typeDesc.UseReflection)
  3291. return obj+".@"+memberName;
  3292. TypeDesc saveTypeDesc = typeDesc;
  3293. while(typeDesc!=null){
  3294. string typeFullName = typeDesc.CSharpName;
  3295. string memberInfoName = GetReflectionVariable(typeFullName, memberName);
  3296. if(memberInfoName != null)
  3297. return memberInfoName+"["+obj+"]";
  3298. // member may be part of the basetype
  3299. typeDesc = typeDesc.BaseTypeDesc;
  3300. if (typeDesc != null && !typeDesc.UseReflection)
  3301. return "(("+typeDesc.CSharpName+")"+obj+").@"+memberName;
  3302. }
  3303. //throw GetReflectionVariableException(saveTypeDesc.CSharpName,memberName);
  3304. // NOTE, Microsoft:Must never happen. If it does let the code
  3305. // gen continue to help debugging what's gone wrong.
  3306. // Eventually the compilation will fail.
  3307. return "["+obj+"]";
  3308. }
  3309. /*
  3310. Exception GetReflectionVariableException(string typeFullName, string memberName){
  3311. string key;
  3312. if(memberName == null)
  3313. key = typeFullName;
  3314. else
  3315. key = memberName+":"+typeFullName;
  3316. System.Text.StringBuilder sb = new System.Text.StringBuilder();
  3317. foreach(object varAvail in reflectionVariables.Keys){
  3318. sb.Append(varAvail.ToString());
  3319. sb.Append("\n");
  3320. }
  3321. return new Exception("No reflection variable for " + key + "\nAvailable keys\n"+sb.ToString());
  3322. }*/
  3323. internal string GetStringForEnumMember(string typeFullName, string memberName, bool useReflection){
  3324. if(!useReflection)
  3325. return typeFullName+".@"+memberName;
  3326. string memberInfoName = GetReflectionVariable(typeFullName, memberName);
  3327. return memberInfoName+"[null]";
  3328. }
  3329. internal string GetStringForArrayMember(string arrayName, string subscript, TypeDesc arrayTypeDesc){
  3330. if (!arrayTypeDesc.UseReflection){
  3331. return arrayName+"["+subscript+"]";
  3332. }
  3333. string typeFullName = arrayTypeDesc.IsCollection ? arrayTypeDesc.CSharpName : typeof(Array).FullName;
  3334. string arrayInfo = GetReflectionVariable(typeFullName, arrayMemberKey);
  3335. return arrayInfo + "["+arrayName + ", "+subscript+"]";
  3336. }
  3337. internal string GetStringForMethod(string obj, string typeFullName, string memberName, bool useReflection){
  3338. if(!useReflection)
  3339. return obj+"."+memberName+"(";
  3340. string memberInfoName = GetReflectionVariable(typeFullName, memberName);
  3341. return memberInfoName+".Invoke("+obj+", new object[]{";
  3342. }
  3343. internal string GetStringForCreateInstance(string escapedTypeName, bool useReflection, bool ctorInaccessible, bool cast) {
  3344. return GetStringForCreateInstance(escapedTypeName, useReflection, ctorInaccessible, cast, string.Empty);
  3345. }
  3346. internal string GetStringForCreateInstance(string escapedTypeName, bool useReflection, bool ctorInaccessible, bool cast, string arg) {
  3347. if (!useReflection && !ctorInaccessible)
  3348. return "new " + escapedTypeName + "(" + arg + ")";
  3349. return GetStringForCreateInstance(GetStringForTypeof(escapedTypeName, useReflection), cast && !useReflection ? escapedTypeName : null, ctorInaccessible, arg);
  3350. }
  3351. internal string GetStringForCreateInstance(string type, string cast, bool nonPublic, string arg) {
  3352. StringBuilder createInstance = new StringBuilder();
  3353. if (cast != null && cast.Length > 0) {
  3354. createInstance.Append("(");
  3355. createInstance.Append(cast);
  3356. createInstance.Append(")");
  3357. }
  3358. createInstance.Append(typeof(Activator).FullName);
  3359. createInstance.Append(".CreateInstance(");
  3360. createInstance.Append(type);
  3361. createInstance.Append(", ");
  3362. string bindingFlags = typeof(BindingFlags).FullName;
  3363. createInstance.Append(bindingFlags);
  3364. createInstance.Append(".Instance | ");
  3365. createInstance.Append(bindingFlags);
  3366. createInstance.Append(".Public | ");
  3367. createInstance.Append(bindingFlags);
  3368. createInstance.Append(".CreateInstance");
  3369. if (nonPublic) {
  3370. createInstance.Append(" | ");
  3371. createInstance.Append(bindingFlags);
  3372. createInstance.Append(".NonPublic");
  3373. }
  3374. if (arg == null || arg.Length == 0) {
  3375. createInstance.Append(", null, new object[0], null)");
  3376. }
  3377. else {
  3378. createInstance.Append(", null, new object[] { ");
  3379. createInstance.Append(arg);
  3380. createInstance.Append(" }, null)");
  3381. }
  3382. return createInstance.ToString();
  3383. }
  3384. internal void WriteLocalDecl(string typeFullName, string variableName, string initValue, bool useReflection) {
  3385. if (useReflection)
  3386. typeFullName = "object";
  3387. writer.Write(typeFullName);
  3388. writer.Write(" ");
  3389. writer.Write(variableName);
  3390. if (initValue != null){
  3391. writer.Write(" = ");
  3392. if(!useReflection && initValue != "null"){
  3393. writer.Write("("+typeFullName+")");
  3394. }
  3395. writer.Write(initValue);
  3396. }
  3397. writer.WriteLine(";");
  3398. }
  3399. internal void WriteCreateInstance(string escapedName, string source, bool useReflection, bool ctorInaccessible) {
  3400. writer.Write(useReflection ? "object" : escapedName);
  3401. writer.Write(" ");
  3402. writer.Write(source);
  3403. writer.Write(" = ");
  3404. writer.Write(GetStringForCreateInstance(escapedName, useReflection, ctorInaccessible, !useReflection && ctorInaccessible));
  3405. writer.WriteLine(";");
  3406. }
  3407. internal void WriteInstanceOf(string source, string escapedTypeName, bool useReflection){
  3408. if(!useReflection){
  3409. writer.Write(source);
  3410. writer.Write(" is ");
  3411. writer.Write(escapedTypeName);
  3412. return;
  3413. }
  3414. writer.Write(GetReflectionVariable(escapedTypeName,null));
  3415. writer.Write(".IsAssignableFrom(");
  3416. writer.Write(source);
  3417. writer.Write(".GetType())");
  3418. }
  3419. internal void WriteArrayLocalDecl( string typeName, string variableName, string initValue, TypeDesc arrayTypeDesc) {
  3420. if (arrayTypeDesc.UseReflection){
  3421. if(arrayTypeDesc.IsEnumerable)
  3422. typeName = typeof(IEnumerable).FullName;
  3423. else if (arrayTypeDesc.IsCollection)
  3424. typeName = typeof(ICollection).FullName;
  3425. else
  3426. typeName = typeof(Array).FullName;
  3427. }
  3428. writer.Write(typeName);
  3429. writer.Write(" ");
  3430. writer.Write(variableName);
  3431. if (initValue != null){
  3432. writer.Write(" = ");
  3433. if (initValue != "null")
  3434. writer.Write("("+typeName+")");
  3435. writer.Write(initValue);
  3436. }
  3437. writer.WriteLine(";");
  3438. }
  3439. internal void WriteEnumCase(string fullTypeName, ConstantMapping c, bool useReflection) {
  3440. writer.Write("case ");
  3441. if (useReflection){
  3442. writer.Write(c.Value.ToString(CultureInfo.InvariantCulture));
  3443. }
  3444. else{
  3445. writer.Write(fullTypeName);
  3446. writer.Write(".@");
  3447. CodeIdentifier.CheckValidIdentifier(c.Name);
  3448. writer.Write(c.Name);
  3449. }
  3450. writer.Write(": ");
  3451. }
  3452. internal void WriteTypeCompare(string variable, string escapedTypeName, bool useReflection){
  3453. writer.Write(variable);
  3454. writer.Write(" == ");
  3455. writer.Write(GetStringForTypeof(escapedTypeName, useReflection));
  3456. }
  3457. internal void WriteArrayTypeCompare(string variable, string escapedTypeName, string elementTypeName, bool useReflection){
  3458. if(!useReflection){
  3459. writer.Write(variable);
  3460. writer.Write(" == typeof(");
  3461. writer.Write(escapedTypeName);
  3462. writer.Write(")");
  3463. return;
  3464. }
  3465. writer.Write(variable);
  3466. writer.Write(".IsArray ");
  3467. writer.Write(" && ");
  3468. WriteTypeCompare(variable+".GetElementType()", elementTypeName, useReflection);
  3469. }
  3470. internal static void WriteQuotedCSharpString(IndentedWriter writer, string value) {
  3471. if (value == null) {
  3472. writer.Write("null");
  3473. return;
  3474. }
  3475. writer.Write("@\"");
  3476. foreach (char ch in value) {
  3477. if (ch < 32) {
  3478. if (ch == '\r')
  3479. writer.Write("\\r");
  3480. else if (ch == '\n')
  3481. writer.Write("\\n");
  3482. else if (ch == '\t')
  3483. writer.Write("\\t");
  3484. else {
  3485. byte b = (byte)ch;
  3486. writer.Write("\\x");
  3487. writer.Write(hexDigits[b >> 4]);
  3488. writer.Write(hexDigits[b & 0xF]);
  3489. }
  3490. }
  3491. else if (ch == '\"') {
  3492. writer.Write("\"\"");
  3493. }
  3494. else {
  3495. writer.Write(ch);
  3496. }
  3497. }
  3498. writer.Write("\"");
  3499. }
  3500. internal void WriteQuotedCSharpString(string value) {
  3501. WriteQuotedCSharpString(writer, value);
  3502. }
  3503. static string helperClassesForUseReflection = @"
  3504. sealed class XSFieldInfo {{
  3505. {3} fieldInfo;
  3506. public XSFieldInfo({2} t, {1} memberName){{
  3507. fieldInfo = t.GetField(memberName);
  3508. }}
  3509. public {0} this[{0} o] {{
  3510. get {{
  3511. return fieldInfo.GetValue(o);
  3512. }}
  3513. set {{
  3514. fieldInfo.SetValue(o, value);
  3515. }}
  3516. }}
  3517. }}
  3518. sealed class XSPropInfo {{
  3519. {4} propInfo;
  3520. public XSPropInfo({2} t, {1} memberName){{
  3521. propInfo = t.GetProperty(memberName);
  3522. }}
  3523. public {0} this[{0} o] {{
  3524. get {{
  3525. return propInfo.GetValue(o, null);
  3526. }}
  3527. set {{
  3528. propInfo.SetValue(o, value, null);
  3529. }}
  3530. }}
  3531. }}
  3532. sealed class XSArrayInfo {{
  3533. {4} propInfo;
  3534. public XSArrayInfo({4} propInfo){{
  3535. this.propInfo = propInfo;
  3536. }}
  3537. public {0} this[{0} a, int i] {{
  3538. get {{
  3539. return propInfo.GetValue(a, new {0}[]{{i}});
  3540. }}
  3541. set {{
  3542. propInfo.SetValue(a, value, new {0}[]{{i}});
  3543. }}
  3544. }}
  3545. }}
  3546. ";
  3547. }
  3548. }