2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.XML / System.Xml.Serialization / SerializationCodeGenerator.cs
blob4e43a4f2a87f1ad0eeefbc2dc07c7af05621897c
1 //
2 // System.Xml.Serialization.SerializationCodeGenerator.cs:
3 //
4 // Authors:
5 // Lluis Sanchez Gual (lluis@ximian.com)
6 // Atsushi Enomoto (atsushi@ximian.com)
7 //
8 // (C) 2002, 2003 Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2006 Novell, Inc.
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.IO;
34 using System.Reflection;
35 using System.Xml.Serialization;
36 using System.Collections;
37 using System.Globalization;
38 using System.Text;
40 using HookDir = System.Xml.Serialization.XmlMappingAccess;
42 namespace System.Xml.Serialization
44 internal class SerializationCodeGenerator
46 XmlMapping _typeMap;
47 SerializationFormat _format;
48 TextWriter _writer;
49 int _tempVarId = 0;
50 int _indent = 0;
51 Hashtable _uniqueNames = new Hashtable();
52 int _methodId = 0;
53 SerializerInfo _config;
54 ArrayList _mapsToGenerate = new ArrayList ();
55 ArrayList _fixupCallbacks;
56 ArrayList _referencedTypes = new ArrayList ();
57 GenerationResult[] _results;
58 GenerationResult _result;
59 XmlMapping[] _xmlMaps;
61 CodeIdentifiers classNames = new CodeIdentifiers ();
63 public SerializationCodeGenerator (XmlMapping[] xmlMaps): this (xmlMaps, null)
67 public SerializationCodeGenerator (XmlMapping[] xmlMaps, SerializerInfo config)
69 _xmlMaps = xmlMaps;
70 _config = config;
73 public SerializationCodeGenerator (XmlMapping xmlMap, SerializerInfo config)
75 _xmlMaps = new XmlMapping [] {xmlMap};
76 _config = config;
79 public static void Generate (string configFileName, string outputPath)
81 SerializationCodeGeneratorConfiguration cnf = null;
82 StreamReader sr = new StreamReader (configFileName);
83 try
85 XmlReflectionImporter ri = new XmlReflectionImporter ();
86 ri.AllowPrivateTypes = true;
87 XmlSerializer ser = new XmlSerializer (ri.ImportTypeMapping (typeof (SerializationCodeGeneratorConfiguration)));
88 cnf = (SerializationCodeGeneratorConfiguration) ser.Deserialize (sr);
90 finally
92 sr.Close ();
95 if (outputPath == null) outputPath = "";
97 CodeIdentifiers ids = new CodeIdentifiers ();
98 if (cnf.Serializers != null)
100 foreach (SerializerInfo info in cnf.Serializers)
102 Type type;
103 if (info.Assembly != null)
105 Assembly asm;
106 try {
107 asm = Assembly.Load (info.Assembly);
108 } catch {
109 asm = Assembly.LoadFrom (info.Assembly);
111 type = asm.GetType (info.ClassName, true);
113 else
114 type = Type.GetType (info.ClassName);
116 if (type == null) throw new InvalidOperationException ("Type " + info.ClassName + " not found");
118 string file = info.OutFileName;
119 if (file == null || file.Length == 0) {
120 int i = info.ClassName.LastIndexOf (".");
121 if (i != -1) file = info.ClassName.Substring (i+1);
122 else file = info.ClassName;
123 file = ids.AddUnique (file, type) + "Serializer.cs";
125 StreamWriter writer = new StreamWriter (Path.Combine (outputPath, file));
129 XmlTypeMapping map;
131 if (info.SerializationFormat == SerializationFormat.Literal) {
132 XmlReflectionImporter ri = new XmlReflectionImporter ();
133 map = ri.ImportTypeMapping (type);
135 else {
136 SoapReflectionImporter ri = new SoapReflectionImporter ();
137 map = ri.ImportTypeMapping (type);
140 SerializationCodeGenerator gen = new SerializationCodeGenerator (map, info);
141 gen.GenerateSerializers (writer);
143 finally
145 writer.Close ();
151 public void GenerateSerializers (TextWriter writer)
153 _writer = writer;
154 _results = new GenerationResult [_xmlMaps.Length];
156 WriteLine ("// It is automatically generated");
157 WriteLine ("using System;");
158 WriteLine ("using System.Xml;");
159 WriteLine ("using System.Xml.Schema;");
160 WriteLine ("using System.Xml.Serialization;");
161 WriteLine ("using System.Text;");
162 WriteLine ("using System.Collections;");
163 WriteLine ("using System.Globalization;");
164 if (_config != null && _config.NamespaceImports != null && _config.NamespaceImports.Length > 0) {
165 foreach (string ns in _config.NamespaceImports)
166 WriteLine ("using " + ns + ";");
168 WriteLine ("");
170 string readerClassName = null;
171 string writerClassName = null;
172 string baseClassName = null;
173 string implClassName = null;
174 string namspace = null;
176 if (_config != null)
178 readerClassName = _config.ReaderClassName;
179 writerClassName = _config.WriterClassName;
180 baseClassName = _config.BaseSerializerClassName;
181 implClassName = _config.ImplementationClassName;
182 namspace = _config.Namespace;
185 if (readerClassName == null || readerClassName.Length == 0)
186 readerClassName = "GeneratedReader";
188 if (writerClassName == null || writerClassName.Length == 0)
189 writerClassName = "GeneratedWriter";
190 if (baseClassName == null || baseClassName.Length == 0)
191 baseClassName = "BaseXmlSerializer";
192 if (implClassName == null || implClassName.Length == 0)
193 implClassName = "XmlSerializerContract";
194 readerClassName = GetUniqueClassName (readerClassName);
195 writerClassName = GetUniqueClassName (writerClassName);
196 baseClassName = GetUniqueClassName (baseClassName);
197 implClassName = GetUniqueClassName (implClassName);
198 Hashtable mapsByNamespace = new Hashtable ();
199 Hashtable generatedMaps = new Hashtable ();
201 for (int n=0; n<_xmlMaps.Length; n++)
203 _typeMap = _xmlMaps [n];
204 if (_typeMap == null) continue;
206 _result = generatedMaps [_typeMap] as GenerationResult;
207 if (_result != null) {
208 _results[n] = _result;
209 continue;
212 _result = new GenerationResult ();
213 _results[n] = _result;
215 generatedMaps [_typeMap] = _result;
217 string typeName;
218 if (_typeMap is XmlTypeMapping) typeName = CodeIdentifier.MakeValid (((XmlTypeMapping)_typeMap).TypeData.CSharpName);
219 else typeName = ((XmlMembersMapping)_typeMap).ElementName;
221 _result.ReaderClassName = readerClassName;
222 _result.WriterClassName = writerClassName;
223 _result.BaseSerializerClassName = baseClassName;
224 _result.ImplementationClassName = implClassName;
226 if (namspace == null || namspace.Length == 0)
227 _result.Namespace = "Mono.GeneratedSerializers." + _typeMap.Format;
228 else
229 _result.Namespace = namspace;
231 _result.WriteMethodName = GetUniqueName ("rwo", _typeMap, "WriteRoot_" + typeName);
232 _result.ReadMethodName = GetUniqueName ("rro", _typeMap, "ReadRoot_" + typeName);
234 _result.Mapping = _typeMap;
236 ArrayList maps = (ArrayList) mapsByNamespace [_result.Namespace];
237 if (maps == null) {
238 maps = new ArrayList ();
239 mapsByNamespace [_result.Namespace] = maps;
241 maps.Add (_result);
244 foreach (DictionaryEntry entry in mapsByNamespace)
246 ArrayList maps = (ArrayList) entry.Value;
248 WriteLine ("namespace " + entry.Key);
249 WriteLineInd ("{");
251 if (_config == null || !_config.NoReader)
252 GenerateReader (readerClassName, maps);
253 WriteLine ("");
254 if (_config == null || !_config.NoWriter)
255 GenerateWriter (writerClassName, maps);
256 WriteLine ("");
258 #if NET_2_0
259 GenerateContract (maps);
260 #endif
262 WriteLineUni ("}");
263 WriteLine ("");
267 public GenerationResult[] GenerationResults
269 get { return _results; }
272 public ArrayList ReferencedTypes
274 get { return _referencedTypes; }
277 void UpdateGeneratedTypes (ArrayList list)
279 for (int n=0; n<list.Count; n++)
281 XmlTypeMapping map = list[n] as XmlTypeMapping;
282 if (map != null && !_referencedTypes.Contains (map.TypeData.Type))
283 _referencedTypes.Add (map.TypeData.Type);
287 static string ToCSharpFullName (Type type)
289 return TypeData.ToCSharpName (type, true);
292 #region Writer Generation
294 //*******************************************************
295 // Contract generation
298 #if NET_2_0
299 public void GenerateContract (ArrayList generatedMaps)
301 // Write the base serializer
303 if (generatedMaps.Count == 0) return;
305 GenerationResult main = (GenerationResult) generatedMaps[0];
307 string baseSerializerName = main.BaseSerializerClassName;
308 string access_mod = (_config == null || !_config.GenerateAsInternal) ? "public" : "internal";
310 WriteLine ("");
311 WriteLine (access_mod + " class " + baseSerializerName + " : System.Xml.Serialization.XmlSerializer");
312 WriteLineInd ("{");
313 WriteLineInd ("protected override System.Xml.Serialization.XmlSerializationReader CreateReader () {");
314 WriteLine ("return new " + main.ReaderClassName + " ();");
315 WriteLineUni ("}");
316 WriteLine ("");
318 WriteLineInd ("protected override System.Xml.Serialization.XmlSerializationWriter CreateWriter () {");
319 WriteLine ("return new " + main.WriterClassName + " ();");
320 WriteLineUni ("}");
321 WriteLine ("");
323 WriteLineInd ("public override bool CanDeserialize (System.Xml.XmlReader xmlReader) {");
324 WriteLine ("return true;");
325 WriteLineUni ("}");
327 WriteLineUni ("}");
328 WriteLine ("");
330 // Write a serializer for each imported map
332 foreach (GenerationResult res in generatedMaps)
334 res.SerializerClassName = GetUniqueClassName (res.Mapping.ElementName + "Serializer");
336 WriteLine (access_mod + " sealed class " + res.SerializerClassName + " : " + baseSerializerName);
337 WriteLineInd ("{");
338 WriteLineInd ("protected override void Serialize (object obj, System.Xml.Serialization.XmlSerializationWriter writer) {");
339 WriteLine ("((" + res.WriterClassName + ")writer)." + res.WriteMethodName + "(obj);");
340 WriteLineUni ("}");
341 WriteLine ("");
343 WriteLineInd ("protected override object Deserialize (System.Xml.Serialization.XmlSerializationReader reader) {");
344 WriteLine ("return ((" + res.ReaderClassName + ")reader)." + res.ReadMethodName + "();");
345 WriteLineUni ("}");
347 WriteLineUni ("}");
348 WriteLine ("");
351 WriteLine ("#if !TARGET_JVM"); // does it make sense? ;-)
352 WriteLine (access_mod + " class " + main.ImplementationClassName + " : System.Xml.Serialization.XmlSerializerImplementation");
353 WriteLineInd ("{");
355 WriteLine ("System.Collections.Hashtable readMethods = null;");
356 WriteLine ("System.Collections.Hashtable writeMethods = null;");
357 WriteLine ("System.Collections.Hashtable typedSerializers = null;");
358 WriteLine ("");
360 WriteLineInd ("public override System.Xml.Serialization.XmlSerializationReader Reader {");
361 WriteLineInd ("get {");
362 WriteLine ("return new " + main.ReaderClassName + "();");
363 WriteLineUni ("}");
364 WriteLineUni ("}");
365 WriteLine ("");
367 WriteLineInd ("public override System.Xml.Serialization.XmlSerializationWriter Writer {");
368 WriteLineInd ("get {");
369 WriteLine ("return new " + main.WriterClassName + "();");
370 WriteLineUni ("}");
371 WriteLineUni ("}");
372 WriteLine ("");
374 WriteLineInd ("public override System.Collections.Hashtable ReadMethods {");
375 WriteLineInd ("get {");
376 WriteLineInd ("lock (this) {");
377 WriteLineInd ("if (readMethods == null) {");
378 WriteLine ("readMethods = new System.Collections.Hashtable ();");
379 foreach (GenerationResult res in generatedMaps)
380 WriteLine ("readMethods.Add (@\"" + res.Mapping.GetKey () + "\", @\"" + res.ReadMethodName + "\");");
381 WriteLineUni ("}");
382 WriteLine ("return readMethods;");
383 WriteLineUni ("}");
384 WriteLineUni ("}");
385 WriteLineUni ("}");
386 WriteLine ("");
388 WriteLineInd ("public override System.Collections.Hashtable WriteMethods {");
389 WriteLineInd ("get {");
390 WriteLineInd ("lock (this) {");
391 WriteLineInd ("if (writeMethods == null) {");
392 WriteLine ("writeMethods = new System.Collections.Hashtable ();");
393 foreach (GenerationResult res in generatedMaps)
394 WriteLine ("writeMethods.Add (@\"" + res.Mapping.GetKey () + "\", @\"" + res.WriteMethodName + "\");");
395 WriteLineUni ("}");
396 WriteLine ("return writeMethods;");
397 WriteLineUni ("}");
398 WriteLineUni ("}");
399 WriteLineUni ("}");
400 WriteLine ("");
402 WriteLineInd ("public override System.Collections.Hashtable TypedSerializers {");
403 WriteLineInd ("get {");
404 WriteLineInd ("lock (this) {");
405 WriteLineInd ("if (typedSerializers == null) {");
406 WriteLine ("typedSerializers = new System.Collections.Hashtable ();");
407 foreach (GenerationResult res in generatedMaps)
408 WriteLine ("typedSerializers.Add (@\"" + res.Mapping.GetKey () + "\", new " + res.SerializerClassName + "());");
409 WriteLineUni ("}");
410 WriteLine ("return typedSerializers;");
411 WriteLineUni ("}");
412 WriteLineUni ("}");
413 WriteLineUni ("}");
414 WriteLine ("");
416 WriteLine ("public override XmlSerializer GetSerializer (Type type)");
417 WriteLineInd ("{");
418 WriteLine ("switch (type.FullName) {");
419 foreach (GenerationResult res in generatedMaps) {
420 if (res.Mapping is XmlTypeMapping) {
421 WriteLineInd ("case \"" + ((XmlTypeMapping) res.Mapping).TypeData.CSharpFullName + "\":");
422 WriteLine ("return (XmlSerializer) TypedSerializers [\"" + res.Mapping.GetKey () + "\"];");
423 WriteLineUni ("");
426 WriteLine ("}");
427 WriteLine ("return base.GetSerializer (type);");
428 WriteLineUni ("}");
429 WriteLine ("");
431 WriteLineInd ("public override bool CanSerialize (System.Type type) {");
432 foreach (GenerationResult res in generatedMaps) {
433 if (res.Mapping is XmlTypeMapping)
434 WriteLine ("if (type == typeof(" + (res.Mapping as XmlTypeMapping).TypeData.CSharpFullName + ")) return true;");
436 WriteLine ("return false;");
437 WriteLineUni ("}");
439 WriteLineUni ("}");
440 WriteLine ("");
441 WriteLine ("#endif");
443 #endif
446 //*******************************************************
447 // Writer generation
450 public void GenerateWriter (string writerClassName, ArrayList maps)
452 _mapsToGenerate = new ArrayList ();
454 InitHooks ();
456 if (_config == null || !_config.GenerateAsInternal)
457 WriteLine ("public class " + writerClassName + " : XmlSerializationWriter");
458 else
459 WriteLine ("internal class " + writerClassName + " : XmlSerializationWriter");
460 WriteLineInd ("{");
461 WriteLine ("const string xmlNamespace = \"http://www.w3.org/2000/xmlns/\";");
462 // ToBinHexString() is not public, so use reflection here.
463 WriteLine ("static readonly System.Reflection.MethodInfo toBinHexStringMethod = typeof (XmlConvert).GetMethod (\"ToBinHexString\", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic, null, new Type [] {typeof (byte [])}, null);");
464 WriteLine ("static string ToBinHexString (byte [] input)");
465 WriteLineInd ("{");
466 WriteLine ("return input == null ? null : (string) toBinHexStringMethod.Invoke (null, new object [] {input});");
467 WriteLineUni ("}");
469 for (int n=0; n<maps.Count; n++)
471 GenerationResult res = (GenerationResult) maps [n];
472 _typeMap = res.Mapping;
473 _format = _typeMap.Format;
474 _result = res;
476 GenerateWriteRoot ();
479 for (int n=0; n<_mapsToGenerate.Count; n++)
481 XmlTypeMapping map = (XmlTypeMapping) _mapsToGenerate[n];
482 GenerateWriteObject (map);
483 if (map.TypeData.SchemaType == SchemaTypes.Enum)
484 GenerateGetXmlEnumValue (map);
487 GenerateWriteInitCallbacks ();
488 UpdateGeneratedTypes (_mapsToGenerate);
490 WriteLineUni ("}");
493 void GenerateWriteRoot ()
495 WriteLine ("public void " +_result.WriteMethodName + " (object o)");
496 WriteLineInd ("{");
497 WriteLine ("WriteStartDocument ();");
499 if (_typeMap is XmlTypeMapping)
501 WriteLine (GetRootTypeName () + " ob = (" + GetRootTypeName () + ") o;");
502 XmlTypeMapping mp = (XmlTypeMapping) _typeMap;
503 if (mp.TypeData.SchemaType == SchemaTypes.Class || mp.TypeData.SchemaType == SchemaTypes.Array)
504 WriteLine ("TopLevelElement ();");
506 if (_format == SerializationFormat.Literal) {
507 WriteLine (GetWriteObjectName (mp) + " (ob, " + GetLiteral(mp.ElementName) + ", " + GetLiteral(mp.Namespace) + ", true, false, true);");
509 else {
510 RegisterReferencingMap (mp);
511 WriteLine ("WritePotentiallyReferencingElement (" + GetLiteral(mp.ElementName) + ", " + GetLiteral(mp.Namespace) + ", ob, " + GetTypeOf(mp.TypeData) + ", true, false);");
514 else if (_typeMap is XmlMembersMapping) {
515 WriteLine ("object[] pars = (object[]) o;");
516 GenerateWriteMessage ((XmlMembersMapping) _typeMap);
518 else
519 throw new InvalidOperationException ("Unknown type map");
521 if (_format == SerializationFormat.Encoded)
522 WriteLine ("WriteReferencedElements ();");
524 WriteLineUni ("}");
525 WriteLine ("");
528 void GenerateWriteMessage (XmlMembersMapping membersMap)
530 if (membersMap.HasWrapperElement) {
531 WriteLine ("TopLevelElement ();");
532 WriteLine ("WriteStartElement (" + GetLiteral (membersMap.ElementName) + ", " + GetLiteral (membersMap.Namespace) + ", (" + GetLiteral(_format == SerializationFormat.Encoded) + "));");
534 /* WriteLineInd ("if (Writer.LookupPrefix (XmlSchema.Namespace) == null)");
535 WriteLine ("WriteAttribute (\"xmlns\",\"xsd\",XmlSchema.Namespace,XmlSchema.Namespace);");
536 Unindent ();
538 WriteLineInd ("if (Writer.LookupPrefix (XmlSchema.InstanceNamespace) == null)");
539 WriteLine ("WriteAttribute (\"xmlns\",\"xsi\",XmlSchema.InstanceNamespace,XmlSchema.InstanceNamespace);");
540 Unindent ();
544 GenerateWriteObjectElement (membersMap, "pars", true);
546 if (membersMap.HasWrapperElement)
547 WriteLine ("WriteEndElement();");
550 void GenerateGetXmlEnumValue (XmlTypeMapping map)
552 EnumMap emap = (EnumMap) map.ObjectMap;
554 string xmlNamesArray = null;
555 string valuesArray = null;
557 if (emap.IsFlags) {
558 // create static string[] holding XML names of enum constants
559 xmlNamesArray = GetUniqueName ("gxe", map, "_xmlNames" + map.XmlType);
560 Write ("static readonly string[] " + xmlNamesArray + " = { ");
561 for (int i = 0; i < emap.XmlNames.Length; i++) {
562 if (i > 0)
563 _writer.Write (',');
564 _writer.Write ('"');
565 _writer.Write (emap.XmlNames[i]);
566 _writer.Write ('\"');
568 _writer.WriteLine (" };");
570 // create const long[] holding values of enum constants
571 valuesArray = GetUniqueName ("gve", map, "_values" + map.XmlType);
572 Write ("static readonly long[] " + valuesArray + " = { ");
573 for (int i = 0; i < emap.Values.Length; i++) {
574 if (i > 0)
575 _writer.Write (',');
576 _writer.Write (emap.Values[i].ToString (CultureInfo.InvariantCulture));
577 _writer.Write ("L");
579 _writer.WriteLine (" };");
580 WriteLine (string.Empty);
583 WriteLine ("string " + GetGetEnumValueName (map) + " (" + map.TypeData.CSharpFullName + " val)");
584 WriteLineInd ("{");
587 WriteLineInd ("switch (val) {");
588 for (int i = 0; i < emap.EnumNames.Length; i++)
589 WriteLine ("case " + map.TypeData.CSharpFullName + ".@" + emap.EnumNames[i] + ": return " + GetLiteral (emap.XmlNames[i]) + ";");
591 if (emap.IsFlags) {
592 WriteLineInd ("default:");
593 // FromEnum actually covers this case too, but we save some cycles here
594 WriteLine ("if (val.ToString () == \"0\") return string.Empty;");
595 Write ("return FromEnum ((long) val, " + xmlNamesArray + ", " + valuesArray);
596 #if NET_2_0
597 _writer.Write (", typeof (");
598 _writer.Write (map.TypeData.CSharpFullName);
599 _writer.Write (").FullName");
600 #endif
601 _writer.Write (')'); // close FromEnum method call
602 WriteUni (";"); // end statement
603 } else {
604 #if NET_2_0
605 WriteLine ("default: throw CreateInvalidEnumValueException ((long) val, typeof (" + map.TypeData.CSharpFullName + ").FullName);");
606 #else
607 WriteLine ("default: return ((long)val).ToString(CultureInfo.InvariantCulture);");
608 #endif
611 WriteLineUni ("}");
613 WriteLineUni ("}");
614 WriteLine ("");
617 void GenerateWriteObject (XmlTypeMapping typeMap)
619 WriteLine ("void " + GetWriteObjectName (typeMap) + " (" + typeMap.TypeData.CSharpFullName + " ob, string element, string namesp, bool isNullable, bool needType, bool writeWrappingElem)");
620 WriteLineInd ("{");
622 PushHookContext ();
624 SetHookVar ("$TYPE", typeMap.TypeData.CSharpName);
625 SetHookVar ("$FULLTYPE", typeMap.TypeData.CSharpFullName);
626 SetHookVar ("$OBJECT", "ob");
627 SetHookVar ("$NULLABLE", "isNullable");
629 if (GenerateWriteHook (HookType.type, typeMap.TypeData.Type))
631 WriteLineUni ("}");
632 WriteLine ("");
633 PopHookContext ();
634 return;
637 if (!typeMap.TypeData.IsValueType)
639 WriteLine ("if (((object)ob) == null)");
640 WriteLineInd ("{");
641 WriteLineInd ("if (isNullable)");
643 if (_format == SerializationFormat.Literal)
644 WriteLine ("WriteNullTagLiteral(element, namesp);");
645 else
646 WriteLine ("WriteNullTagEncoded (element, namesp);");
648 WriteLineUni ("return;");
649 WriteLineUni ("}");
650 WriteLine ("");
653 if (typeMap.TypeData.SchemaType == SchemaTypes.XmlNode)
655 if (_format == SerializationFormat.Literal)
656 WriteLine ("WriteElementLiteral (ob, \"\", \"\", true, false);");
657 else
658 WriteLine ("WriteElementEncoded (ob, \"\", \"\", true, false);");
660 GenerateEndHook ();
661 WriteLineUni ("}");
662 WriteLine ("");
663 PopHookContext ();
664 return;
667 if (typeMap.TypeData.SchemaType == SchemaTypes.XmlSerializable)
669 WriteLine ("WriteSerializable (ob, element, namesp, isNullable);");
671 GenerateEndHook ();
672 WriteLineUni ("}");
673 WriteLine ("");
674 PopHookContext ();
675 return;
678 ArrayList types = typeMap.DerivedTypes;
680 WriteLine ("System.Type type = ob.GetType ();");
681 WriteLine ("if (type == typeof(" + typeMap.TypeData.CSharpFullName + "))");
682 WriteLine ("{ }");
684 for (int n=0; n<types.Count; n++)
686 XmlTypeMapping map = (XmlTypeMapping)types[n];
688 WriteLineInd ("else if (type == typeof(" + map.TypeData.CSharpFullName + ")) { ");
689 WriteLine (GetWriteObjectName (map) + "((" + map.TypeData.CSharpFullName + ")ob, element, namesp, isNullable, true, writeWrappingElem);");
690 WriteLine ("return;");
691 WriteLineUni ("}");
694 if (typeMap.TypeData.Type == typeof (object)) {
695 WriteLineInd ("else {");
696 WriteLineInd ("if (ob.GetType().IsArray && typeof(XmlNode).IsAssignableFrom(ob.GetType().GetElementType())) {");
697 WriteLine ("Writer.WriteStartElement (" + GetLiteral (typeMap.ElementName) + ", " + GetLiteral (typeMap.Namespace) + ");");
698 WriteLineInd ("foreach (XmlNode node in (System.Collections.IEnumerable) ob)");
699 WriteLineUni ("node.WriteTo (Writer);");
700 WriteLineUni ("Writer.WriteEndElement ();");
701 WriteLine ("}");
702 WriteLineInd ("else");
703 WriteLineUni ("WriteTypedPrimitive (element, namesp, ob, true);");
704 WriteLine ("return;");
705 WriteLineUni ("}");
707 else
709 WriteLineInd ("else {");
710 WriteLine ("throw CreateUnknownTypeException (ob);");
711 WriteLineUni ("}");
712 WriteLine ("");
714 WriteLineInd ("if (writeWrappingElem) {");
715 if (_format == SerializationFormat.Encoded) WriteLine ("needType = true;");
716 WriteLine ("WriteStartElement (element, namesp, ob);");
717 WriteLineUni ("}");
718 WriteLine ("");
720 WriteLine ("if (needType) WriteXsiType(" + GetLiteral(typeMap.XmlType) + ", " + GetLiteral(typeMap.XmlTypeNamespace) + ");");
721 WriteLine ("");
723 switch (typeMap.TypeData.SchemaType)
725 case SchemaTypes.Class: GenerateWriteObjectElement (typeMap, "ob", false); break;
726 case SchemaTypes.Array: GenerateWriteListElement (typeMap, "ob"); break;
727 case SchemaTypes.Primitive: GenerateWritePrimitiveElement (typeMap, "ob"); break;
728 case SchemaTypes.Enum: GenerateWriteEnumElement (typeMap, "ob"); break;
731 WriteLine ("if (writeWrappingElem) WriteEndElement (ob);");
734 GenerateEndHook ();
735 WriteLineUni ("}");
736 WriteLine ("");
737 PopHookContext ();
740 void GenerateWriteObjectElement (XmlMapping xmlMap, string ob, bool isValueList)
742 XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
743 Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
745 ClassMap map = (ClassMap)xmlMap.ObjectMap;
746 if (!GenerateWriteHook (HookType.attributes, xmlMapType))
748 if (map.NamespaceDeclarations != null) {
749 WriteLine ("WriteNamespaceDeclarations ((XmlSerializerNamespaces) " + ob + ".@" + map.NamespaceDeclarations.Name + ");");
750 WriteLine ("");
753 XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
754 if (anyAttrMember != null)
756 if (!GenerateWriteMemberHook (xmlMapType, anyAttrMember))
758 string cond = GenerateMemberHasValueCondition (anyAttrMember, ob, isValueList);
759 if (cond != null) WriteLineInd ("if (" + cond + ") {");
761 string tmpVar = GetObTempVar ();
762 WriteLine ("ICollection " + tmpVar + " = " + GenerateGetMemberValue (anyAttrMember, ob, isValueList) + ";");
763 WriteLineInd ("if (" + tmpVar + " != null) {");
765 string tmpVar2 = GetObTempVar ();
766 WriteLineInd ("foreach (XmlAttribute " + tmpVar2 + " in " + tmpVar + ")");
767 WriteLineInd ("if (" + tmpVar2 + ".NamespaceURI != xmlNamespace)");
768 WriteLine ("WriteXmlAttribute (" + tmpVar2 + ", " + ob + ");");
769 Unindent ();
770 Unindent ();
771 WriteLineUni ("}");
773 if (cond != null) WriteLineUni ("}");
774 WriteLine ("");
775 GenerateEndHook ();
779 ICollection attributes = map.AttributeMembers;
780 if (attributes != null)
782 foreach (XmlTypeMapMemberAttribute attr in attributes)
784 if (GenerateWriteMemberHook (xmlMapType, attr)) continue;
786 string val = GenerateGetMemberValue (attr, ob, isValueList);
787 string cond = GenerateMemberHasValueCondition (attr, ob, isValueList);
789 if (cond != null) WriteLineInd ("if (" + cond + ") {");
791 string strVal = GenerateGetStringValue (attr.MappedType, attr.TypeData, val, false);
792 WriteLine ("WriteAttribute (" + GetLiteral(attr.AttributeName) + ", " + GetLiteral(attr.Namespace) + ", " + strVal + ");");
794 if (cond != null) WriteLineUni ("}");
795 GenerateEndHook ();
797 WriteLine ("");
799 GenerateEndHook ();
802 if (!GenerateWriteHook (HookType.elements, xmlMapType))
804 ICollection members = map.ElementMembers;
805 if (members != null)
807 foreach (XmlTypeMapMemberElement member in members)
809 if (GenerateWriteMemberHook (xmlMapType, member)) continue;
811 string cond = GenerateMemberHasValueCondition (member, ob, isValueList);
812 if (cond != null) WriteLineInd ("if (" + cond + ") {");
814 string memberValue = GenerateGetMemberValue (member, ob, isValueList);
815 Type memType = member.GetType();
817 if (memType == typeof(XmlTypeMapMemberList))
819 GenerateWriteMemberElement ((XmlTypeMapElementInfo) member.ElementInfo[0], memberValue);
821 else if (memType == typeof(XmlTypeMapMemberFlatList))
823 WriteLineInd ("if (" + memberValue + " != null) {");
824 GenerateWriteListContent (ob, member.TypeData, ((XmlTypeMapMemberFlatList)member).ListMap, memberValue, false);
825 WriteLineUni ("}");
827 else if (memType == typeof(XmlTypeMapMemberAnyElement))
829 WriteLineInd ("if (" + memberValue + " != null) {");
830 GenerateWriteAnyElementContent ((XmlTypeMapMemberAnyElement)member, memberValue);
831 WriteLineUni ("}");
833 else if (memType == typeof(XmlTypeMapMemberAnyElement))
835 WriteLineInd ("if (" + memberValue + " != null) {");
836 GenerateWriteAnyElementContent ((XmlTypeMapMemberAnyElement)member, memberValue);
837 WriteLineUni ("}");
839 else if (memType == typeof(XmlTypeMapMemberAnyAttribute))
841 // Ignore
843 else if (memType == typeof(XmlTypeMapMemberElement))
845 if (member.ElementInfo.Count == 1) {
846 GenerateWriteMemberElement ((XmlTypeMapElementInfo)member.ElementInfo[0], memberValue);
848 else if (member.ChoiceMember != null)
850 string choiceValue = ob + ".@" + member.ChoiceMember;
851 foreach (XmlTypeMapElementInfo elem in member.ElementInfo) {
852 WriteLineInd ("if (" + choiceValue + " == " + GetLiteral(elem.ChoiceValue) + ") {");
853 GenerateWriteMemberElement (elem, GetCast(elem.TypeData, member.TypeData, memberValue));
854 WriteLineUni ("}");
857 else
859 // WriteLineInd ("if (" + memberValue + " == null) {");
860 // GenerateWriteMemberElement ((XmlTypeMapElementInfo)member.ElementInfo[0], memberValue);
861 // WriteLineUni ("}");
863 bool first = true;
864 foreach (XmlTypeMapElementInfo elem in member.ElementInfo)
866 WriteLineInd ((first?"":"else ") + "if (" + memberValue + " is " + elem.TypeData.CSharpFullName + ") {");
867 GenerateWriteMemberElement (elem, GetCast(elem.TypeData, member.TypeData, memberValue));
868 WriteLineUni ("}");
869 first = false;
873 else
874 throw new InvalidOperationException ("Unknown member type");
876 if (cond != null)
877 WriteLineUni ("}");
879 GenerateEndHook ();
882 GenerateEndHook ();
886 void GenerateWriteMemberElement (XmlTypeMapElementInfo elem, string memberValue)
888 switch (elem.TypeData.SchemaType)
890 case SchemaTypes.XmlNode:
891 string elemName = elem.WrappedElement ? elem.ElementName : "";
892 if (_format == SerializationFormat.Literal)
893 WriteMetCall ("WriteElementLiteral", memberValue, GetLiteral(elemName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false");
894 else
895 WriteMetCall ("WriteElementEncoded", memberValue, GetLiteral(elemName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false");
896 break;
898 case SchemaTypes.Enum:
899 case SchemaTypes.Primitive:
900 if (_format == SerializationFormat.Literal)
901 GenerateWritePrimitiveValueLiteral (memberValue, elem.ElementName, elem.Namespace, elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
902 else
903 GenerateWritePrimitiveValueEncoded (memberValue, elem.ElementName, elem.Namespace, new XmlQualifiedName (elem.TypeData.XmlType, elem.DataTypeNamespace), elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
904 break;
906 case SchemaTypes.Array:
907 WriteLineInd ("if (" + memberValue + " != null) {");
909 if (elem.MappedType.MultiReferenceType) {
910 WriteMetCall ("WriteReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, GetLiteral(elem.IsNullable));
911 RegisterReferencingMap (elem.MappedType);
913 else {
914 WriteMetCall ("WriteStartElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue);
915 GenerateWriteListContent (null, elem.TypeData, (ListMap) elem.MappedType.ObjectMap, memberValue, false);
916 WriteMetCall ("WriteEndElement", memberValue);
918 WriteLineUni ("}");
920 if (elem.IsNullable) {
921 WriteLineInd ("else");
922 if (_format == SerializationFormat.Literal)
923 WriteMetCall ("WriteNullTagLiteral", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace));
924 else
925 WriteMetCall ("WriteNullTagEncoded", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace));
926 Unindent ();
929 break;
931 case SchemaTypes.Class:
932 if (elem.MappedType.MultiReferenceType) {
933 RegisterReferencingMap (elem.MappedType);
934 if (elem.MappedType.TypeData.Type == typeof(object))
935 WriteMetCall ("WritePotentiallyReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, "null", "false", GetLiteral(elem.IsNullable));
936 else
937 WriteMetCall ("WriteReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, GetLiteral(elem.IsNullable));
939 else
940 WriteMetCall (GetWriteObjectName(elem.MappedType), memberValue, GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false", "true");
941 break;
943 case SchemaTypes.XmlSerializable:
944 WriteMetCall ("WriteSerializable", "(" + ToCSharpFullName (elem.MappedType.TypeData.Type) + ") " + memberValue, GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable));
945 break;
947 default:
948 throw new NotSupportedException ("Invalid value type");
952 void GenerateWriteListElement (XmlTypeMapping typeMap, string ob)
954 if (_format == SerializationFormat.Encoded)
956 string n, ns;
957 string itemCount = GenerateGetListCount (typeMap.TypeData, ob);
958 GenerateGetArrayType ((ListMap) typeMap.ObjectMap, itemCount, out n, out ns);
960 string arrayType;
961 if (ns != string.Empty)
962 arrayType = "FromXmlQualifiedName (new XmlQualifiedName(" + n + "," + ns + "))";
963 else
964 arrayType = GetLiteral (n);
966 WriteMetCall ("WriteAttribute", GetLiteral("arrayType"), GetLiteral(XmlSerializer.EncodingNamespace), arrayType);
968 GenerateWriteListContent (null, typeMap.TypeData, (ListMap) typeMap.ObjectMap, ob, false);
971 void GenerateWriteAnyElementContent (XmlTypeMapMemberAnyElement member, string memberValue)
973 bool singleElement = (member.TypeData.Type == typeof (XmlElement));
974 string var, var2;
976 var2 = GetObTempVar ();
977 if (singleElement)
978 var = memberValue;
979 else {
980 var = GetObTempVar ();
981 WriteLineInd ("foreach (object " + var2 + " in " + memberValue + ") {");
983 WriteLine ("XmlNode " + var + " = " + var2 + " as XmlNode;");
984 WriteLine ("if (" + var + " == null && " + var2 + "!= null) throw new InvalidOperationException (\"A member with XmlAnyElementAttribute can only serialize and deserialize certain XmlNode types.");
985 WriteLineUni ("}");
987 string elem = GetObTempVar ();
988 WriteLine ("XmlNode " + elem + " = " + var + ";");
989 WriteLine ("if (" + elem + " is XmlElement) {");
991 if (!member.IsDefaultAny) {
992 for (int n=0; n<member.ElementInfo.Count; n++) {
993 XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)member.ElementInfo[n];
994 string txt = "(" + elem + ".LocalName == " + GetLiteral(info.ElementName) + " && " + elem + ".NamespaceURI == " + GetLiteral(info.Namespace) + ")";
995 if (n == member.ElementInfo.Count-1) txt += ") {";
996 if (n == 0) WriteLineInd ("if (" + txt);
997 else WriteLine ("|| " + txt);
1000 WriteLine ("}");
1001 WriteLine ("else " + elem + ".WriteTo (Writer);");
1003 if (_format == SerializationFormat.Literal)
1004 WriteLine ("WriteElementLiteral (" + elem + ", \"\", \"\", false, true);");
1005 else
1006 WriteLine ("WriteElementEncoded (" + elem + ", \"\", \"\", false, true);");
1008 if (!member.IsDefaultAny) {
1009 WriteLineUni ("}");
1010 WriteLineInd ("else");
1011 WriteLine ("throw CreateUnknownAnyElementException (" + elem + ".Name, " + elem + ".NamespaceURI);");
1012 Unindent ();
1015 if (!singleElement)
1016 WriteLineUni ("}");
1019 void GenerateWritePrimitiveElement (XmlTypeMapping typeMap, string ob)
1021 string strVal = GenerateGetStringValue (typeMap, typeMap.TypeData, ob, false);
1022 WriteLine ("Writer.WriteString (" + strVal + ");");
1025 void GenerateWriteEnumElement (XmlTypeMapping typeMap, string ob)
1027 string strVal = GenerateGetEnumXmlValue (typeMap, ob);
1028 WriteLine ("Writer.WriteString (" + strVal + ");");
1031 string GenerateGetStringValue (XmlTypeMapping typeMap, TypeData type, string value, bool isNullable)
1033 if (type.SchemaType == SchemaTypes.Array) {
1034 string str = GetStrTempVar ();
1035 WriteLine ("string " + str + " = null;");
1036 WriteLineInd ("if (" + value + " != null) {");
1037 string res = GenerateWriteListContent (null, typeMap.TypeData, (ListMap)typeMap.ObjectMap, value, true);
1038 WriteLine (str + " = " + res + ".ToString ().Trim ();");
1039 WriteLineUni ("}");
1040 return str;
1042 else if (type.SchemaType == SchemaTypes.Enum) {
1043 if (isNullable)
1044 return "(" + value + ").HasValue ? " + GenerateGetEnumXmlValue (typeMap, "(" + value + ").Value") + " : null";
1045 else
1046 return GenerateGetEnumXmlValue (typeMap, value);
1048 else if (type.Type == typeof (XmlQualifiedName))
1049 return "FromXmlQualifiedName (" + value + ")";
1050 else if (value == null)
1051 return null;
1052 else
1053 return XmlCustomFormatter.GenerateToXmlString (type, value);
1056 string GenerateGetEnumXmlValue (XmlTypeMapping typeMap, string ob)
1058 return GetGetEnumValueName (typeMap) + " (" + ob + ")";
1061 string GenerateGetListCount (TypeData listType, string ob)
1063 if (listType.Type.IsArray)
1064 return "ob.Length";
1065 else
1066 return "ob.Count";
1069 void GenerateGetArrayType (ListMap map, string itemCount, out string localName, out string ns)
1071 string arrayDim;
1072 if (itemCount != "") arrayDim = "";
1073 else arrayDim = "[]";
1075 XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) map.ItemInfo[0];
1076 if (info.TypeData.SchemaType == SchemaTypes.Array)
1078 string nm;
1079 GenerateGetArrayType ((ListMap)info.MappedType.ObjectMap, "", out nm, out ns);
1080 localName = nm + arrayDim;
1082 else
1084 if (info.MappedType != null)
1086 localName = info.MappedType.XmlType + arrayDim;
1087 ns = info.MappedType.Namespace;
1089 else
1091 localName = info.TypeData.XmlType + arrayDim;
1092 ns = info.DataTypeNamespace;
1095 if (itemCount != "") {
1096 localName = "\"" + localName + "[\" + " + itemCount + " + \"]\"";
1097 ns = GetLiteral (ns);
1101 string GenerateWriteListContent (string container, TypeData listType, ListMap map, string ob, bool writeToString)
1103 string targetString = null;
1105 if (writeToString)
1107 targetString = GetStrTempVar ();
1108 WriteLine ("System.Text.StringBuilder " + targetString + " = new System.Text.StringBuilder();");
1111 if (listType.Type.IsArray)
1113 string itemVar = GetNumTempVar ();
1114 WriteLineInd ("for (int "+itemVar+" = 0; "+itemVar+" < " + ob + ".Length; "+itemVar+"++) {");
1115 GenerateListLoop (container, map, ob + "["+itemVar+"]", itemVar, listType.ListItemTypeData, targetString);
1116 WriteLineUni ("}");
1118 else if (typeof(ICollection).IsAssignableFrom (listType.Type))
1120 string itemVar = GetNumTempVar ();
1121 WriteLineInd ("for (int "+itemVar+" = 0; "+itemVar+" < " + ob + ".Count; "+itemVar+"++) {");
1122 GenerateListLoop (container, map, ob + "["+itemVar+"]", itemVar, listType.ListItemTypeData, targetString);
1123 WriteLineUni ("}");
1125 else if (typeof(IEnumerable).IsAssignableFrom (listType.Type))
1127 string itemVar = GetObTempVar ();
1128 WriteLineInd ("foreach (" + listType.ListItemTypeData.CSharpFullName + " " + itemVar + " in " + ob + ") {");
1129 GenerateListLoop (container, map, itemVar, null, listType.ListItemTypeData, targetString);
1130 WriteLineUni ("}");
1132 else
1133 throw new Exception ("Unsupported collection type");
1135 return targetString;
1138 void GenerateListLoop (string container, ListMap map, string item, string index, TypeData itemTypeData, string targetString)
1140 bool multichoice = (map.ItemInfo.Count > 1);
1142 if (map.ChoiceMember != null && container != null && index != null) {
1143 WriteLineInd ("if ((" + container + ".@" + map.ChoiceMember + " == null) || (" + index + " >= " + container + ".@" + map.ChoiceMember + ".Length))");
1144 WriteLine ("throw CreateInvalidChoiceIdentifierValueException (" + container + ".GetType().ToString(), \"" + map.ChoiceMember + "\");");
1145 Unindent ();
1148 if (multichoice)
1149 WriteLine ("if (((object)" + item + ") == null) { }");
1151 foreach (XmlTypeMapElementInfo info in map.ItemInfo)
1153 if (map.ChoiceMember != null && multichoice)
1154 WriteLineInd ("else if (" + container + ".@" + map.ChoiceMember + "[" + index + "] == " + GetLiteral (info.ChoiceValue) + ") {");
1155 else if (multichoice)
1156 WriteLineInd ("else if (" + item + ".GetType() == typeof(" + info.TypeData.CSharpFullName + ")) {");
1158 if (targetString == null)
1159 GenerateWriteMemberElement (info, GetCast (info.TypeData, itemTypeData, item));
1160 else
1162 string strVal = GenerateGetStringValue (info.MappedType, info.TypeData, GetCast (info.TypeData, itemTypeData, item), false);
1163 WriteLine (targetString + ".Append (" + strVal + ").Append (\" \");");
1166 if (multichoice)
1167 WriteLineUni ("}");
1170 if (multichoice)
1171 WriteLine ("else throw CreateUnknownTypeException (" + item + ");");
1174 void GenerateWritePrimitiveValueLiteral (string memberValue, string name, string ns, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
1176 if (!wrapped) {
1177 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, false);
1178 WriteMetCall ("WriteValue", strVal);
1180 else if (isNullable) {
1181 if (typeData.Type == typeof(XmlQualifiedName))
1182 WriteMetCall ("WriteNullableQualifiedNameLiteral", GetLiteral(name), GetLiteral(ns), memberValue);
1183 else {
1184 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, true);
1185 WriteMetCall ("WriteNullableStringLiteral", GetLiteral(name), GetLiteral(ns), strVal);
1188 else {
1189 if (typeData.Type == typeof(XmlQualifiedName))
1190 WriteMetCall ("WriteElementQualifiedName", GetLiteral(name), GetLiteral(ns), memberValue);
1191 else {
1192 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, false);
1193 WriteMetCall ("WriteElementString", GetLiteral(name),GetLiteral(ns), strVal);
1198 void GenerateWritePrimitiveValueEncoded (string memberValue, string name, string ns, XmlQualifiedName xsiType, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
1200 if (!wrapped) {
1201 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, false);
1202 WriteMetCall ("WriteValue", strVal);
1204 else if (isNullable) {
1205 if (typeData.Type == typeof(XmlQualifiedName))
1206 WriteMetCall ("WriteNullableQualifiedNameEncoded", GetLiteral(name), GetLiteral(ns), memberValue, GetLiteral(xsiType));
1207 else {
1208 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, true);
1209 WriteMetCall ("WriteNullableStringEncoded", GetLiteral(name), GetLiteral(ns), strVal, GetLiteral(xsiType));
1212 else {
1213 if (typeData.Type == typeof(XmlQualifiedName))
1214 WriteMetCall ("WriteElementQualifiedName", GetLiteral(name), GetLiteral(ns), memberValue, GetLiteral(xsiType));
1215 else {
1216 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, false);
1217 WriteMetCall ("WriteElementString", GetLiteral(name),GetLiteral(ns), strVal, GetLiteral(xsiType));
1222 string GenerateGetMemberValue (XmlTypeMapMember member, string ob, bool isValueList)
1224 if (isValueList) return GetCast (member.TypeData, TypeTranslator.GetTypeData (typeof(object)), ob + "[" + member.GlobalIndex + "]");
1225 else return ob + ".@" + member.Name;
1228 string GenerateMemberHasValueCondition (XmlTypeMapMember member, string ob, bool isValueList)
1230 if (isValueList) {
1231 return ob + ".Length > " + member.GlobalIndex;
1233 else if (member.DefaultValue != System.DBNull.Value) {
1234 string mem = ob + ".@" + member.Name;
1235 if (member.DefaultValue == null)
1236 return mem + " != null";
1237 else if (member.TypeData.SchemaType == SchemaTypes.Enum)
1238 return mem + " != " + GetCast (member.TypeData, GetLiteral (member.DefaultValue));
1239 else
1240 return mem + " != " + GetLiteral (member.DefaultValue);
1242 else if (member.IsOptionalValueType)
1243 return ob + ".@" + member.Name + "Specified";
1244 return null;
1247 void GenerateWriteInitCallbacks ()
1249 WriteLine ("protected override void InitCallbacks ()");
1250 WriteLineInd ("{");
1252 if (_format == SerializationFormat.Encoded)
1254 foreach (XmlMapping xmap in _mapsToGenerate) {
1255 XmlTypeMapping map = xmap as XmlTypeMapping;
1256 if (map != null)
1257 WriteMetCall ("AddWriteCallback", GetTypeOf(map.TypeData), GetLiteral(map.XmlType), GetLiteral(map.Namespace), "new XmlSerializationWriteCallback (" + GetWriteObjectCallbackName (map) + ")");
1261 WriteLineUni ("}");
1262 WriteLine ("");
1264 if (_format == SerializationFormat.Encoded)
1266 foreach (XmlTypeMapping xmap in _mapsToGenerate) {
1267 XmlTypeMapping map = xmap as XmlTypeMapping;
1268 if (map == null) continue;
1269 if (map.TypeData.SchemaType == SchemaTypes.Enum)
1270 WriteWriteEnumCallback (map);
1271 else
1272 WriteWriteObjectCallback (map);
1277 void WriteWriteEnumCallback (XmlTypeMapping map)
1279 WriteLine ("void " + GetWriteObjectCallbackName (map) + " (object ob)");
1280 WriteLineInd ("{");
1281 WriteMetCall (GetWriteObjectName(map), GetCast (map.TypeData, "ob"), GetLiteral(map.ElementName), GetLiteral(map.Namespace), "false", "true", "false");
1282 WriteLineUni ("}");
1283 WriteLine ("");
1286 void WriteWriteObjectCallback (XmlTypeMapping map)
1288 WriteLine ("void " + GetWriteObjectCallbackName (map) + " (object ob)");
1289 WriteLineInd ("{");
1290 WriteMetCall (GetWriteObjectName(map), GetCast (map.TypeData, "ob"), GetLiteral(map.ElementName), GetLiteral(map.Namespace), "false", "false", "false");
1291 WriteLineUni ("}");
1292 WriteLine ("");
1295 #endregion
1297 #region Reader Generation
1299 //*******************************************************
1300 // Reader generation
1303 public void GenerateReader (string readerClassName, ArrayList maps)
1305 if (_config == null || !_config.GenerateAsInternal)
1306 WriteLine ("public class " + readerClassName + " : XmlSerializationReader");
1307 else
1308 WriteLine ("internal class " + readerClassName + " : XmlSerializationReader");
1309 WriteLineInd ("{");
1310 // FromBinHexString() is not public, so use reflection here.
1311 WriteLine ("static readonly System.Reflection.MethodInfo fromBinHexStringMethod = typeof (XmlConvert).GetMethod (\"FromBinHexString\", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic, null, new Type [] {typeof (string)}, null);");
1312 WriteLine ("static byte [] FromBinHexString (string input)");
1313 WriteLineInd ("{");
1314 WriteLine ("return input == null ? null : (byte []) fromBinHexStringMethod.Invoke (null, new object [] {input});");
1315 WriteLineUni ("}");
1317 _mapsToGenerate = new ArrayList ();
1318 _fixupCallbacks = new ArrayList ();
1319 InitHooks ();
1321 for (int n=0; n<maps.Count; n++)
1323 GenerationResult res = (GenerationResult) maps [n];
1324 _typeMap = res.Mapping;
1325 _format = _typeMap.Format;
1326 _result = res;
1328 GenerateReadRoot ();
1331 for (int n=0; n<_mapsToGenerate.Count; n++)
1333 XmlTypeMapping map = _mapsToGenerate [n] as XmlTypeMapping;
1334 if (map == null) continue;
1336 GenerateReadObject (map);
1337 if (map.TypeData.SchemaType == SchemaTypes.Enum)
1338 GenerateGetEnumValueMethod (map);
1341 GenerateReadInitCallbacks ();
1343 if (_format == SerializationFormat.Encoded)
1345 GenerateFixupCallbacks ();
1346 GenerateFillerCallbacks ();
1349 WriteLineUni ("}");
1350 UpdateGeneratedTypes (_mapsToGenerate);
1353 void GenerateReadRoot ()
1355 WriteLine ("public object " + _result.ReadMethodName + " ()");
1356 WriteLineInd ("{");
1357 WriteLine ("Reader.MoveToContent();");
1359 if (_typeMap is XmlTypeMapping)
1361 XmlTypeMapping typeMap = (XmlTypeMapping) _typeMap;
1363 if (_format == SerializationFormat.Literal)
1365 if (typeMap.TypeData.SchemaType == SchemaTypes.XmlNode) {
1366 if (typeMap.TypeData.Type == typeof (XmlDocument))
1367 WriteLine ("return ReadXmlDocument (false);");
1368 else
1369 WriteLine ("return ReadXmlNode (false);");
1370 } else {
1371 WriteLineInd ("if (Reader.LocalName != " + GetLiteral (typeMap.ElementName) + " || Reader.NamespaceURI != " + GetLiteral (typeMap.Namespace) + ")");
1372 WriteLine ("throw CreateUnknownNodeException();");
1373 Unindent ();
1375 WriteLine ("return " + GetReadObjectCall (typeMap, GetLiteral(typeMap.IsNullable), "true") + ";");
1378 else
1380 WriteLine ("object ob = null;");
1381 WriteLine ("Reader.MoveToContent();");
1382 WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
1383 WriteLineInd ("{");
1384 WriteLineInd ("if (Reader.LocalName == " + GetLiteral(typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")");
1385 WriteLine ("ob = ReadReferencedElement();");
1386 Unindent ();
1387 WriteLineInd ("else ");
1388 WriteLine ("throw CreateUnknownNodeException();");
1389 Unindent ();
1390 WriteLineUni ("}");
1391 WriteLineInd ("else ");
1392 WriteLine ("UnknownNode(null);");
1393 Unindent ();
1394 WriteLine ("");
1395 WriteLine ("ReadReferencedElements();");
1396 WriteLine ("return ob;");
1397 RegisterReferencingMap (typeMap);
1400 else {
1401 WriteLine ("return " + GenerateReadMessage ((XmlMembersMapping)_typeMap) + ";");
1404 WriteLineUni ("}");
1405 WriteLine ("");
1408 string GenerateReadMessage (XmlMembersMapping typeMap)
1410 WriteLine ("object[] parameters = new object[" + typeMap.Count + "];");
1411 WriteLine ("");
1413 if (typeMap.HasWrapperElement)
1415 if (_format == SerializationFormat.Encoded)
1417 WriteLine ("while (Reader.NodeType == System.Xml.XmlNodeType.Element)");
1418 WriteLineInd ("{");
1419 WriteLine ("string root = Reader.GetAttribute (\"root\", " + GetLiteral(XmlSerializer.EncodingNamespace) + ");");
1420 WriteLine ("if (root == null || System.Xml.XmlConvert.ToBoolean(root)) break;");
1421 WriteLine ("ReadReferencedElement ();");
1422 WriteLine ("Reader.MoveToContent ();");
1423 WriteLineUni ("}");
1424 WriteLine ("");
1425 WriteLine ("if (Reader.NodeType != System.Xml.XmlNodeType.EndElement)");
1426 WriteLineInd ("{");
1427 WriteLineInd ("if (Reader.IsEmptyElement) {");
1428 WriteLine ("Reader.Skip();");
1429 WriteLine ("Reader.MoveToContent();");
1430 WriteLineUni ("}");
1431 WriteLineInd ("else {");
1432 WriteLine ("Reader.ReadStartElement();");
1433 GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, false);
1434 WriteLine ("ReadEndElement();");
1435 WriteLineUni ("}");
1436 WriteLine ("");
1437 WriteLine ("Reader.MoveToContent();");
1438 WriteLineUni ("}");
1440 else
1442 // bug #79988: out parameters need to be initialized if
1443 // they are value types
1444 ClassMap classMap = (ClassMap) typeMap.ObjectMap;
1445 ArrayList members = classMap.AllMembers;
1446 for (int n = 0; n < members.Count; n++) {
1447 XmlTypeMapMember mem = (XmlTypeMapMember) members [n];
1448 if (!mem.IsReturnValue && mem.TypeData.IsValueType)
1449 GenerateSetMemberValueFromAttr (mem, "parameters",
1450 String.Format ("({0}) Activator.CreateInstance(typeof({0}), true)", mem.TypeData.FullTypeName), true);
1453 WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.ReadState == ReadState.Interactive)");
1454 WriteLineInd ("{");
1455 WriteLine ("if (Reader.IsStartElement(" + GetLiteral(typeMap.ElementName) + ", " + GetLiteral(typeMap.Namespace) + "))");
1456 WriteLineInd ("{");
1457 bool dummy = false;
1458 GenerateReadAttributeMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, ref dummy);
1459 WriteLine ("if (Reader.IsEmptyElement)");
1460 WriteLineInd ("{");
1461 WriteLine ("Reader.Skip(); Reader.MoveToContent(); continue;");
1462 WriteLineUni ("}");
1463 WriteLine ("Reader.ReadStartElement();");
1464 GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, false);
1465 WriteLine ("ReadEndElement();");
1466 WriteLine ("break;");
1467 WriteLineUni ("}");
1468 WriteLineInd ("else ");
1469 WriteLine ("UnknownNode(null);");
1470 Unindent ();
1471 WriteLine ("");
1472 WriteLine ("Reader.MoveToContent();");
1473 WriteLineUni ("}");
1476 else
1477 GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, _format == SerializationFormat.Encoded);
1479 if (_format == SerializationFormat.Encoded)
1480 WriteLine ("ReadReferencedElements();");
1482 return "parameters";
1485 void GenerateReadObject (XmlTypeMapping typeMap)
1487 string isNullable;
1488 if (_format == SerializationFormat.Literal) {
1489 WriteLine ("public " + typeMap.TypeData.CSharpFullName + " " + GetReadObjectName (typeMap) + " (bool isNullable, bool checkType)");
1490 isNullable = "isNullable";
1492 else {
1493 WriteLine ("public object " + GetReadObjectName (typeMap) + " ()");
1494 isNullable = "true";
1497 WriteLineInd ("{");
1499 PushHookContext ();
1501 SetHookVar ("$TYPE", typeMap.TypeData.CSharpName);
1502 SetHookVar ("$FULLTYPE", typeMap.TypeData.CSharpFullName);
1503 SetHookVar ("$NULLABLE", "isNullable");
1505 switch (typeMap.TypeData.SchemaType)
1507 case SchemaTypes.Class: GenerateReadClassInstance (typeMap, isNullable, "checkType"); break;
1508 case SchemaTypes.Array:
1509 string list = GenerateReadListElement (typeMap, null, isNullable, true);
1510 if (list != null)
1511 WriteLine ("return " + list + ";");
1512 break;
1513 case SchemaTypes.XmlNode: GenerateReadXmlNodeElement (typeMap, isNullable); break;
1514 case SchemaTypes.Primitive: GenerateReadPrimitiveElement (typeMap, isNullable); break;
1515 case SchemaTypes.Enum: GenerateReadEnumElement (typeMap, isNullable); break;
1516 case SchemaTypes.XmlSerializable: GenerateReadXmlSerializableElement (typeMap, isNullable); break;
1517 default: throw new Exception ("Unsupported map type");
1520 WriteLineUni ("}");
1521 WriteLine ("");
1522 PopHookContext ();
1525 void GenerateReadClassInstance (XmlTypeMapping typeMap, string isNullable, string checkType)
1527 SetHookVar ("$OBJECT", "ob");
1528 if (!typeMap.TypeData.IsValueType)
1530 WriteLine (typeMap.TypeData.CSharpFullName + " ob = null;");
1532 if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) {
1533 WriteLine ("return ob;");
1534 return;
1537 if (_format == SerializationFormat.Literal) {
1538 WriteLine ("if (" + isNullable + " && ReadNull()) return null;");
1539 WriteLine ("");
1540 WriteLine ("if (checkType) ");
1541 WriteLineInd ("{");
1543 else {
1544 WriteLine ("if (ReadNull()) return null;");
1545 WriteLine ("");
1548 else
1550 WriteLine (typeMap.TypeData.CSharpFullName + String.Format (" ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName));
1552 if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) {
1553 WriteLine ("return ob;");
1554 return;
1558 WriteLine ("System.Xml.XmlQualifiedName t = GetXsiType();");
1559 WriteLine ("if (t == null)");
1560 if (typeMap.TypeData.Type != typeof(object))
1561 WriteLine ("{ }");
1562 else
1563 WriteLine ("\treturn " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (new System.Xml.XmlQualifiedName(\"anyType\", System.Xml.Schema.XmlSchema.Namespace))") + ";");
1565 foreach (XmlTypeMapping realMap in typeMap.DerivedTypes)
1567 WriteLineInd ("else if (t.Name == " + GetLiteral (realMap.XmlType) + " && t.Namespace == " + GetLiteral (realMap.XmlTypeNamespace) + ")");
1568 WriteLine ("return " + GetReadObjectCall(realMap, isNullable, checkType) + ";");
1569 Unindent ();
1572 WriteLine ("else if (t.Name != " + GetLiteral (typeMap.XmlType) + " || t.Namespace != " + GetLiteral (typeMap.XmlTypeNamespace) + ")");
1573 if (typeMap.TypeData.Type == typeof(object))
1574 WriteLine ("\treturn " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (t)") + ";");
1575 else
1576 WriteLine ("\tthrow CreateUnknownTypeException(t);");
1578 if (!typeMap.TypeData.IsValueType)
1580 if (_format == SerializationFormat.Literal)
1581 WriteLineUni ("}");
1583 if (typeMap.TypeData.Type.IsAbstract) {
1584 GenerateEndHook ();
1585 WriteLine ("return ob;");
1586 return;
1589 WriteLine ("");
1590 WriteLine (String.Format ("ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName));
1593 WriteLine ("");
1595 WriteLine ("Reader.MoveToElement();");
1596 WriteLine ("");
1598 GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "ob", false, false);
1600 WriteLine ("");
1602 GenerateEndHook ();
1603 WriteLine ("return ob;");
1606 void GenerateReadMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isValueList, bool readByOrder)
1608 XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
1609 Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
1611 bool first = false;
1612 // Read attributes
1613 GenerateReadAttributeMembers (xmlMap, map, ob, isValueList, ref first);
1615 if (!isValueList)
1617 WriteLine ("Reader.MoveToElement();");
1618 WriteLineInd ("if (Reader.IsEmptyElement) {");
1619 WriteLine ("Reader.Skip ();");
1620 GenerateSetListMembersDefaults (typeMap, map, ob, isValueList);
1621 WriteLine ("return " + ob + ";");
1622 WriteLineUni ("}");
1623 WriteLine ("");
1625 WriteLine ("Reader.ReadStartElement();");
1628 // Reads elements
1630 WriteLine("Reader.MoveToContent();");
1631 WriteLine ("");
1633 if (!GenerateReadHook (HookType.elements, xmlMapType))
1635 string[] readFlag = null;
1636 if (map.ElementMembers != null && !readByOrder)
1638 string readFlagsVars = string.Empty;
1639 readFlag = new string[map.ElementMembers.Count];
1640 int n=0;
1641 foreach (XmlTypeMapMember mem in map.ElementMembers) {
1642 // The text collector doesn't need a flag
1643 if (!((mem is XmlTypeMapMemberElement) && ((XmlTypeMapMemberElement)mem).IsXmlTextCollector)) {
1644 readFlag[n] = GetBoolTempVar ();
1645 if (readFlagsVars.Length > 0) readFlagsVars += ", ";
1646 readFlagsVars += readFlag[n] + "=false";
1648 n++;
1650 if (readFlagsVars.Length > 0) {
1651 readFlagsVars = "bool " + readFlagsVars;
1652 WriteLine (readFlagsVars + ";");
1654 WriteLine ("");
1657 string[] indexes = null;
1658 string[] flatLists = null;
1659 string[] flatListsChoices = null;
1661 if (map.FlatLists != null)
1663 indexes = new string[map.FlatLists.Count];
1664 flatLists = new string[map.FlatLists.Count];
1666 string code = "int ";
1667 for (int n=0; n<map.FlatLists.Count; n++)
1669 XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement)map.FlatLists[n];
1670 indexes[n] = GetNumTempVar ();
1671 if (n > 0) code += ", ";
1672 code += indexes[n] + "=0";
1673 if (!MemberHasReadReplaceHook (xmlMapType, mem)) {
1674 flatLists[n] = GetObTempVar ();
1675 string rval;
1676 WriteLine (mem.TypeData.CSharpFullName + " " + flatLists[n] + ";");
1677 if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList)) {
1678 rval = GenerateGetMemberValue (mem, ob, isValueList);
1679 WriteLine (flatLists[n] + " = " + rval + ";");
1680 } else if (mem.TypeData.Type.IsArray) {
1681 rval = GenerateInitializeList (mem.TypeData);
1682 WriteLine (flatLists[n] + " = " + rval + ";");
1683 } else {
1684 WriteLine (flatLists[n] + " = " + GenerateGetMemberValue (mem, ob, isValueList) + ";");
1685 WriteLineInd ("if (((object)" + flatLists[n] + ") == null) {");
1686 WriteLine (flatLists[n] + " = " + GenerateInitializeList (mem.TypeData) + ";");
1687 GenerateSetMemberValue (mem, ob, flatLists[n], isValueList);
1688 WriteLineUni ("}");
1692 if (mem.ChoiceMember != null) {
1693 if (flatListsChoices == null)
1694 flatListsChoices = new string [map.FlatLists.Count];
1695 flatListsChoices[n] = GetObTempVar ();
1696 string rval = GenerateInitializeList (mem.ChoiceTypeData);
1697 WriteLine (mem.ChoiceTypeData.CSharpFullName + " " + flatListsChoices[n] + " = " + rval + ";");
1700 WriteLine (code + ";");
1701 WriteLine ("");
1704 if (_format == SerializationFormat.Encoded && map.ElementMembers != null)
1706 _fixupCallbacks.Add (xmlMap);
1707 WriteLine ("Fixup fixup = new Fixup(" + ob + ", new XmlSerializationFixupCallback(" + GetFixupCallbackName (xmlMap) + "), " + map.ElementMembers.Count + ");");
1708 WriteLine ("AddFixup (fixup);");
1709 WriteLine ("");
1712 ArrayList infos = null;
1714 int maxInd;
1715 if (readByOrder) {
1716 if (map.ElementMembers != null) maxInd = map.ElementMembers.Count;
1717 else maxInd = 0;
1719 else
1721 infos = new ArrayList ();
1722 infos.AddRange (map.AllElementInfos);
1723 maxInd = infos.Count;
1725 WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) ");
1726 WriteLineInd ("{");
1727 WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
1728 WriteLineInd ("{");
1731 first = true;
1732 for (int ind = 0; ind < maxInd; ind++)
1734 XmlTypeMapElementInfo info = readByOrder ? map.GetElement (ind) : (XmlTypeMapElementInfo) infos [ind];
1736 if (!readByOrder)
1738 if (info.IsTextElement || info.IsUnnamedAnyElement) continue;
1739 string elemCond = first ? "" : "else ";
1740 elemCond += "if (";
1741 if (!(info.Member.IsReturnValue && _format == SerializationFormat.Encoded)) {
1742 elemCond += "Reader.LocalName == " + GetLiteral (info.ElementName);
1743 if (!map.IgnoreMemberNamespace) elemCond += " && Reader.NamespaceURI == " + GetLiteral (info.Namespace);
1744 elemCond += " && ";
1746 elemCond += "!" + readFlag[info.Member.Index] + ") {";
1747 WriteLineInd (elemCond);
1750 if (info.Member.GetType() == typeof (XmlTypeMapMemberList))
1752 if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
1754 string list = GetObTempVar ();
1755 WriteLine ("object " + list + " = ReadReferencingElement (out fixup.Ids[" + info.Member.Index + "]);");
1756 RegisterReferencingMap (info.MappedType);
1758 WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {"); // Already read
1759 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList))
1760 WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral(info.TypeData.CSharpFullName) + ");");
1761 else
1762 GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
1763 WriteLineUni ("}");
1765 if (!info.MappedType.TypeData.Type.IsArray)
1767 WriteLineInd ("else {");
1768 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList))
1769 WriteLine (list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
1770 else {
1771 WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
1772 GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
1774 WriteLine ("AddFixup (new CollectionFixup (" + list + ", new XmlSerializationCollectionFixupCallback (" + GetFillListName(info.Member.TypeData) + "), fixup.Ids[" + info.Member.Index + "]));");
1775 WriteLine ("fixup.Ids[" + info.Member.Index + "] = null;"); // The member already has the value, no further fix needed.
1776 WriteLineUni ("}");
1779 else
1781 if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1782 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) {
1783 GenerateReadListElement (info.MappedType, GenerateGetMemberValue (info.Member, ob, isValueList), GetLiteral(info.IsNullable), false);
1784 } else if (info.MappedType.TypeData.Type.IsArray) {
1785 if (info.IsNullable)
1786 GenerateSetMemberValue (info.Member, ob, GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true), isValueList);
1787 else {
1788 string list = GetObTempVar ();
1789 WriteLine (info.MappedType.TypeData.CSharpFullName + " " + list + " = " + GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true) + ";");
1790 WriteLineInd ("if (((object)" + list + ") != null) {");
1791 GenerateSetMemberValue (info.Member, ob, list, isValueList);
1792 WriteLineUni ("}");
1794 } else {
1795 string list = GetObTempVar ();
1796 WriteLine (info.MappedType.TypeData.CSharpFullName + " " + list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
1797 WriteLineInd ("if (((object)" + list + ") == null) {");
1798 WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
1799 GenerateSetMemberValue (info.Member, ob, list, isValueList);
1800 WriteLineUni ("}");
1801 GenerateReadListElement (info.MappedType, list, GetLiteral(info.IsNullable), true);
1803 GenerateEndHook ();
1806 if (!readByOrder)
1807 WriteLine (readFlag[info.Member.Index] + " = true;");
1809 else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
1811 XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
1812 if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
1813 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GenerateReadObjectElement (info), !IsReadOnly (typeMap, info.Member, info.TypeData, isValueList));
1814 if (mem.ChoiceMember != null) {
1815 GenerateAddListValue (mem.ChoiceTypeData, flatListsChoices[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetLiteral (info.ChoiceValue), true);
1817 GenerateEndHook ();
1819 WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1821 else if (info.Member.GetType() == typeof (XmlTypeMapMemberAnyElement))
1823 XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement)info.Member;
1824 if (mem.TypeData.IsListType) {
1825 if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
1826 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetReadXmlNode (mem.TypeData.ListItemTypeData, false), true);
1827 GenerateEndHook ();
1829 WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1831 else {
1832 if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1833 GenerateSetMemberValue (mem, ob, GetReadXmlNode(mem.TypeData, false), isValueList);
1834 GenerateEndHook ();
1838 else if (info.Member.GetType() == typeof(XmlTypeMapMemberElement))
1840 if (!readByOrder)
1841 WriteLine (readFlag[info.Member.Index] + " = true;");
1842 if (_format == SerializationFormat.Encoded)
1844 string val = GetObTempVar ();
1845 RegisterReferencingMap (info.MappedType);
1847 if (info.Member.TypeData.SchemaType != SchemaTypes.Primitive)
1848 WriteLine ("object " + val + " = ReadReferencingElement (out fixup.Ids[" + info.Member.Index + "]);");
1849 else
1850 WriteLine ("object " + val + " = ReadReferencingElement (" + GetLiteral(info.Member.TypeData.XmlType) + ", " + GetLiteral(System.Xml.Schema.XmlSchema.Namespace) + ", out fixup.Ids[" + info.Member.Index + "]);");
1852 if (info.MultiReferenceType)
1853 WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {"); // already read
1854 else
1855 WriteLineInd ("if (" + val + " != null) {"); // null value
1857 GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,val), isValueList);
1858 WriteLineUni ("}");
1860 else if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1861 if (info.ChoiceValue != null) {
1862 XmlTypeMapMemberElement imem = (XmlTypeMapMemberElement) info.Member;
1863 WriteLine (ob + ".@" + imem.ChoiceMember + " = " + GetLiteral(info.ChoiceValue) + ";");
1865 GenerateSetMemberValue (info.Member, ob, GenerateReadObjectElement (info), isValueList);
1866 GenerateEndHook ();
1869 else
1870 throw new InvalidOperationException ("Unknown member type");
1872 if (!readByOrder)
1873 WriteLineUni ("}");
1874 else
1875 WriteLine ("Reader.MoveToContent();");
1876 first = false;
1879 if (!readByOrder)
1881 if (!first) WriteLineInd ("else {");
1883 if (map.DefaultAnyElementMember != null)
1885 XmlTypeMapMemberAnyElement mem = map.DefaultAnyElementMember;
1886 if (mem.TypeData.IsListType) {
1887 if (!GenerateReadArrayMemberHook (xmlMapType, mem, indexes[mem.FlatArrayIndex])) {
1888 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetReadXmlNode(mem.TypeData.ListItemTypeData, false), true);
1889 GenerateEndHook ();
1891 WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1893 else if (! GenerateReadMemberHook (xmlMapType, mem)) {
1894 GenerateSetMemberValue (mem, ob, GetReadXmlNode(mem.TypeData, false), isValueList);
1895 GenerateEndHook ();
1898 else {
1899 if (!GenerateReadHook (HookType.unknownElement, xmlMapType)) {
1900 WriteLine ("UnknownNode (" + ob + ");");
1901 GenerateEndHook ();
1905 if (!first) WriteLineUni ("}");
1907 WriteLineUni ("}");
1909 if (map.XmlTextCollector != null)
1911 WriteLine ("else if (Reader.NodeType == System.Xml.XmlNodeType.Text || Reader.NodeType == System.Xml.XmlNodeType.CDATA)");
1912 WriteLineInd ("{");
1914 if (map.XmlTextCollector is XmlTypeMapMemberExpandable)
1916 XmlTypeMapMemberExpandable mem = (XmlTypeMapMemberExpandable)map.XmlTextCollector;
1917 XmlTypeMapMemberFlatList flatl = mem as XmlTypeMapMemberFlatList;
1918 TypeData itype = (flatl == null) ? mem.TypeData.ListItemTypeData : flatl.ListMap.FindTextElement().TypeData;
1920 if (!GenerateReadArrayMemberHook (xmlMapType, map.XmlTextCollector, indexes[mem.FlatArrayIndex])) {
1921 string val = (itype.Type == typeof (string)) ? "Reader.ReadString()" : GetReadXmlNode (itype, false);
1922 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], val, true);
1923 GenerateEndHook ();
1925 WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1927 else if (!GenerateReadMemberHook (xmlMapType, map.XmlTextCollector))
1929 XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement) map.XmlTextCollector;
1930 XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) mem.ElementInfo [0];
1931 if (info.TypeData.Type == typeof (string))
1932 GenerateSetMemberValue (mem, ob, "ReadString (" + GenerateGetMemberValue (mem, ob, isValueList) + ")", isValueList);
1933 else {
1934 WriteLineInd ("{");
1935 string str = GetStrTempVar ();
1936 WriteLine ("string " + str + " = Reader.ReadString();");
1937 GenerateSetMemberValue (mem, ob, GenerateGetValueFromXmlString (str, info.TypeData, info.MappedType, info.IsNullable), isValueList);
1938 WriteLineUni ("}");
1940 GenerateEndHook ();
1942 WriteLineUni ("}");
1945 WriteLine ("else");
1946 WriteLine ("\tUnknownNode(" + ob + ");");
1947 WriteLine ("");
1948 WriteLine ("Reader.MoveToContent();");
1949 WriteLineUni ("}");
1951 else
1952 WriteLine ("Reader.MoveToContent();");
1954 if (flatLists != null)
1956 WriteLine ("");
1957 foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
1959 if (MemberHasReadReplaceHook (xmlMapType, mem)) continue;
1961 string list = flatLists[mem.FlatArrayIndex];
1962 if (mem.TypeData.Type.IsArray)
1963 WriteLine (list + " = (" + mem.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.TypeData.Type.GetElementType()) + ", true);");
1964 if (!IsReadOnly (typeMap, mem, mem.TypeData, isValueList) && mem.TypeData.Type.IsArray)
1965 GenerateSetMemberValue (mem, ob, list, isValueList);
1969 if (flatListsChoices != null)
1971 WriteLine ("");
1972 foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
1974 if (MemberHasReadReplaceHook (xmlMapType, mem)) continue;
1975 if (mem.ChoiceMember == null) continue;
1977 string list = flatListsChoices[mem.FlatArrayIndex];
1978 WriteLine (list + " = (" + mem.ChoiceTypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.ChoiceTypeData.Type.GetElementType()) + ", true);");
1979 WriteLine (ob + ".@" + mem.ChoiceMember + " = " + list + ";");
1983 GenerateSetListMembersDefaults (typeMap, map, ob, isValueList);
1985 GenerateEndHook ();
1988 if (!isValueList)
1990 WriteLine ("");
1991 WriteLine ("ReadEndElement();");
1995 void GenerateReadAttributeMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isValueList, ref bool first)
1997 XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
1998 Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
2000 if (GenerateReadHook (HookType.attributes, xmlMapType))
2001 return;
2003 XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
2005 if (anyAttrMember != null)
2007 WriteLine ("int anyAttributeIndex = 0;");
2008 WriteLine (anyAttrMember.TypeData.CSharpFullName + " anyAttributeArray = null;");
2011 WriteLine ("while (Reader.MoveToNextAttribute())");
2012 WriteLineInd ("{");
2013 first = true;
2014 if (map.AttributeMembers != null) {
2015 foreach (XmlTypeMapMemberAttribute at in map.AttributeMembers)
2017 WriteLineInd ((first?"":"else ") + "if (Reader.LocalName == " + GetLiteral (at.AttributeName) + " && Reader.NamespaceURI == " + GetLiteral (at.Namespace) + ") {");
2018 if (!GenerateReadMemberHook (xmlMapType, at)) {
2019 GenerateSetMemberValue (at, ob, GenerateGetValueFromXmlString ("Reader.Value", at.TypeData, at.MappedType, false), isValueList);
2020 GenerateEndHook ();
2022 WriteLineUni ("}");
2023 first = false;
2026 WriteLineInd ((first?"":"else ") + "if (IsXmlnsAttribute (Reader.Name)) {");
2028 // If the map has NamespaceDeclarations,
2029 // then store this xmlns to the given member.
2030 // If the instance doesn't exist, then create.
2032 if (map.NamespaceDeclarations != null) {
2033 if (!GenerateReadMemberHook (xmlMapType, map.NamespaceDeclarations)) {
2034 string nss = ob + ".@" + map.NamespaceDeclarations.Name;
2035 WriteLine ("if (" + nss + " == null) " + nss + " = new XmlSerializerNamespaces ();");
2036 WriteLineInd ("if (Reader.Prefix == \"xmlns\")");
2037 WriteLine (nss + ".Add (Reader.LocalName, Reader.Value);");
2038 Unindent ();
2039 WriteLineInd ("else");
2040 WriteLine (nss + ".Add (\"\", Reader.Value);");
2041 Unindent ();
2042 GenerateEndHook ();
2046 WriteLineUni ("}");
2047 WriteLineInd ("else {");
2049 if (anyAttrMember != null)
2051 if (!GenerateReadArrayMemberHook (xmlMapType, anyAttrMember, "anyAttributeIndex")) {
2052 WriteLine ("System.Xml.XmlAttribute attr = (System.Xml.XmlAttribute) Document.ReadNode(Reader);");
2053 if (typeof(System.Xml.Schema.XmlSchemaAnnotated).IsAssignableFrom (xmlMapType))
2054 WriteLine ("ParseWsdlArrayType (attr);");
2055 GenerateAddListValue (anyAttrMember.TypeData, "anyAttributeArray", "anyAttributeIndex", GetCast (anyAttrMember.TypeData.ListItemTypeData, "attr"), true);
2056 GenerateEndHook ();
2058 WriteLine ("anyAttributeIndex++;");
2060 else {
2061 if (!GenerateReadHook (HookType.unknownAttribute, xmlMapType)) {
2062 WriteLine ("UnknownNode (" + ob + ");");
2063 GenerateEndHook ();
2067 WriteLineUni ("}");
2068 WriteLineUni ("}");
2070 if (anyAttrMember != null && !MemberHasReadReplaceHook (xmlMapType, anyAttrMember))
2072 WriteLine ("");
2073 WriteLine("anyAttributeArray = (" + anyAttrMember.TypeData.CSharpFullName + ") ShrinkArray (anyAttributeArray, anyAttributeIndex, " + GetTypeOf(anyAttrMember.TypeData.Type.GetElementType()) + ", true);");
2074 GenerateSetMemberValue (anyAttrMember, ob, "anyAttributeArray", isValueList);
2076 WriteLine ("");
2077 WriteLine ("Reader.MoveToElement ();");
2079 GenerateEndHook ();
2082 void GenerateSetListMembersDefaults (XmlTypeMapping typeMap, ClassMap map, string ob, bool isValueList)
2084 if (map.ListMembers != null)
2086 ArrayList members = map.ListMembers;
2087 for (int n=0; n<members.Count; n++) {
2088 XmlTypeMapMember mem = (XmlTypeMapMember) members[n];
2089 if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList))
2090 continue;
2091 WriteLineInd ("if (" + GenerateGetMemberValue (mem, ob, isValueList) + " == null) {");
2092 GenerateSetMemberValue (mem, ob, GenerateInitializeList (mem.TypeData), isValueList);
2093 WriteLineUni ("}");
2098 bool IsReadOnly (XmlTypeMapping map, XmlTypeMapMember member, TypeData memType, bool isValueList)
2100 if (isValueList) return !memType.HasPublicConstructor;
2101 else return member.IsReadOnly (map.TypeData.Type) || !memType.HasPublicConstructor;
2104 void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList)
2106 if (isValueList) WriteLine (ob + "[" + member.GlobalIndex + "] = " + value + ";");
2107 else {
2108 WriteLine (ob + ".@" + member.Name + " = " + value + ";");
2109 if (member.IsOptionalValueType)
2110 WriteLine (ob + "." + member.Name + "Specified = true;");
2114 void GenerateSetMemberValueFromAttr (XmlTypeMapMember member, string ob, string value, bool isValueList)
2116 // Enumeration values specified in custom attributes are stored as integer
2117 // values if the custom attribute property is of type object. So, it is
2118 // necessary to convert to the enum type before asigning the value to the field.
2120 if (member.TypeData.Type.IsEnum)
2121 value = GetCast (member.TypeData.Type, value);
2122 GenerateSetMemberValue (member, ob, value, isValueList);
2125 string GenerateReadObjectElement (XmlTypeMapElementInfo elem)
2127 switch (elem.TypeData.SchemaType)
2129 case SchemaTypes.XmlNode:
2130 return GetReadXmlNode (elem.TypeData, true);
2132 case SchemaTypes.Primitive:
2133 case SchemaTypes.Enum:
2134 return GenerateReadPrimitiveValue (elem);
2136 case SchemaTypes.Array:
2137 return GenerateReadListElement (elem.MappedType, null, GetLiteral(elem.IsNullable), true);
2139 case SchemaTypes.Class:
2140 return GetReadObjectCall (elem.MappedType, GetLiteral(elem.IsNullable), "true");
2142 case SchemaTypes.XmlSerializable:
2143 return GetCast (elem.TypeData, String.Format ("({0}) ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true))", elem.TypeData.CSharpFullName));
2145 default:
2146 throw new NotSupportedException ("Invalid value type");
2150 string GenerateReadPrimitiveValue (XmlTypeMapElementInfo elem)
2152 if (elem.TypeData.Type == typeof (XmlQualifiedName)) {
2153 if (elem.IsNullable) return "ReadNullableQualifiedName ()";
2154 else return "ReadElementQualifiedName ()";
2156 else if (elem.IsNullable) {
2157 string str = GetStrTempVar ();
2158 WriteLine ("string " + str + " = ReadNullableString ();");
2159 return GenerateGetValueFromXmlString (str, elem.TypeData, elem.MappedType, true);
2161 else {
2162 string str = GetStrTempVar ();
2163 WriteLine ("string " + str + " = Reader.ReadElementString ();");
2164 return GenerateGetValueFromXmlString (str, elem.TypeData, elem.MappedType, false);
2168 string GenerateGetValueFromXmlString (string value, TypeData typeData, XmlTypeMapping typeMap, bool isNullable)
2170 if (typeData.SchemaType == SchemaTypes.Array)
2171 return GenerateReadListString (typeMap, value);
2172 else if (typeData.SchemaType == SchemaTypes.Enum)
2173 return GenerateGetEnumValue (typeMap, value, isNullable);
2174 else if (typeData.Type == typeof (XmlQualifiedName))
2175 return "ToXmlQualifiedName (" + value + ")";
2176 else
2177 return XmlCustomFormatter.GenerateFromXmlString (typeData, value);
2180 string GenerateReadListElement (XmlTypeMapping typeMap, string list, string isNullable, bool canCreateInstance)
2182 Type listType = typeMap.TypeData.Type;
2183 ListMap listMap = (ListMap)typeMap.ObjectMap;
2184 bool doNullCheck = typeMap.TypeData.Type.IsArray;
2186 if (canCreateInstance && typeMap.TypeData.HasPublicConstructor)
2188 if (list == null) {
2189 list = GetObTempVar ();
2190 WriteLine (typeMap.TypeData.CSharpFullName + " " + list + " = null;");
2191 if (doNullCheck)
2192 WriteLineInd ("if (!ReadNull()) {");
2193 WriteLine (list + " = " + GenerateCreateList (listType) + ";");
2194 } else {
2195 if (doNullCheck)
2196 WriteLineInd ("if (!ReadNull()) {");
2199 else
2201 if (list != null) {
2202 WriteLineInd ("if (((object)" + list + ") == null)");
2203 WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeData.CSharpFullName) + ");");
2204 Unindent ();
2205 doNullCheck = false;
2207 else {
2208 WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeData.CSharpFullName) + ");");
2209 return list;
2213 WriteLineInd ("if (Reader.IsEmptyElement) {");
2214 WriteLine ("Reader.Skip();");
2215 if (listType.IsArray)
2216 WriteLine (list + " = (" + typeMap.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", 0, " + GetTypeOf(listType.GetElementType()) + ", false);");
2218 Unindent ();
2219 WriteLineInd ("} else {");
2221 string index = GetNumTempVar ();
2222 WriteLine ("int " + index + " = 0;");
2223 WriteLine ("Reader.ReadStartElement();");
2224 WriteLine ("Reader.MoveToContent();");
2225 WriteLine ("");
2227 WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) ");
2228 WriteLineInd ("{");
2229 WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
2230 WriteLineInd ("{");
2232 bool first = true;
2233 foreach (XmlTypeMapElementInfo elemInfo in listMap.ItemInfo)
2235 WriteLineInd ((first?"":"else ") + "if (Reader.LocalName == " + GetLiteral (elemInfo.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (elemInfo.Namespace) + ") {");
2236 GenerateAddListValue (typeMap.TypeData, list, index, GenerateReadObjectElement (elemInfo), false);
2237 WriteLine (index + "++;");
2238 WriteLineUni ("}");
2239 first = false;
2241 if (!first) WriteLine ("else UnknownNode (null);");
2242 else WriteLine ("UnknownNode (null);");
2244 WriteLineUni ("}");
2245 WriteLine ("else UnknownNode (null);");
2246 WriteLine ("");
2247 WriteLine ("Reader.MoveToContent();");
2248 WriteLineUni ("}");
2250 WriteLine ("ReadEndElement();");
2252 if (listType.IsArray)
2253 WriteLine (list + " = (" + typeMap.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + index + ", " + GetTypeOf(listType.GetElementType()) + ", false);");
2255 WriteLineUni ("}");
2256 if (doNullCheck)
2257 WriteLineUni ("}");
2259 return list;
2262 string GenerateReadListString (XmlTypeMapping typeMap, string values)
2264 Type listType = typeMap.TypeData.Type;
2265 ListMap listMap = (ListMap)typeMap.ObjectMap;
2266 string itemType = ToCSharpFullName (listType.GetElementType());
2268 string list = GetObTempVar ();
2269 WriteLine (itemType + "[] " + list + ";");
2271 string var = GetStrTempVar ();
2272 WriteLine ("string " + var + " = " + values + ".Trim();");
2273 WriteLineInd ("if (" + var + " != string.Empty) {");
2275 string valueArray = GetObTempVar ();
2276 WriteLine ("string[] " + valueArray + " = " + var + ".Split (' ');");
2278 WriteLine (list + " = new " + GetArrayDeclaration (listType, valueArray + ".Length") + ";");
2280 XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)listMap.ItemInfo[0];
2282 string index = GetNumTempVar ();
2283 WriteLineInd ("for (int " + index + " = 0; " + index + " < " + valueArray + ".Length; " + index + "++)");
2284 WriteLine (list + "[" + index + "] = " + GenerateGetValueFromXmlString (valueArray + "[" + index + "]", info.TypeData, info.MappedType, info.IsNullable) + ";");
2285 Unindent ();
2286 WriteLineUni ("}");
2287 WriteLine ("else");
2288 WriteLine ("\t" + list + " = new " + GetArrayDeclaration (listType, "0") + ";");
2290 return list;
2293 string GetArrayDeclaration (Type type, string length)
2295 Type t = type.GetElementType();
2296 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
2297 sb.Append ('[').Append (length).Append (']');
2298 while (t.IsArray) {
2299 sb.Append ("[]");
2300 t = t.GetElementType();
2302 sb.Insert (0, ToCSharpFullName (t));
2303 return sb.ToString ();
2306 void GenerateAddListValue (TypeData listType, string list, string index, string value, bool canCreateInstance)
2308 Type type = listType.Type;
2309 if (type.IsArray)
2311 WriteLine (list + " = (" + ToCSharpFullName (type) + ") EnsureArrayIndex (" + list + ", " + index + ", " + GetTypeOf(type.GetElementType()) + ");");
2312 WriteLine (list + "[" + index + "] = " + value + ";");
2314 else // Must be IEnumerable
2316 WriteLine ("if (((object)" + list + ") == null)");
2317 if (canCreateInstance)
2318 WriteLine ("\t" + list + String.Format (" = ({0}) Activator.CreateInstance(typeof({0}), true);", listType.CSharpFullName));
2319 else
2320 WriteLine ("\tthrow CreateReadOnlyCollectionException (" + GetLiteral (listType.CSharpFullName) + ");");
2322 WriteLine (list + ".Add (" + value + ");");
2326 string GenerateCreateList (Type listType)
2328 if (listType.IsArray)
2329 return "(" + ToCSharpFullName (listType) + ") EnsureArrayIndex (null, 0, " + GetTypeOf(listType.GetElementType()) + ")";
2330 else
2331 return "new " + ToCSharpFullName (listType) + "()";
2334 string GenerateInitializeList (TypeData listType)
2336 if (listType.Type.IsArray)
2337 return "null";
2338 else
2339 return "new " + listType.CSharpFullName + "()";
2342 void GenerateFillerCallbacks ()
2344 foreach (TypeData td in _listsToFill)
2346 string metName = GetFillListName (td);
2347 WriteLine ("void " + metName + " (object list, object source)");
2348 WriteLineInd ("{");
2349 WriteLine ("if (((object)list) == null) throw CreateReadOnlyCollectionException (" + GetLiteral (td.CSharpFullName) + ");");
2350 WriteLine ("");
2352 WriteLine (td.CSharpFullName + " dest = (" + td.CSharpFullName + ") list;");
2353 WriteLine ("foreach (object ob in (IEnumerable)source)");
2354 WriteLine ("\tdest.Add (" + GetCast (td.ListItemTypeData, "ob") + ");");
2355 WriteLineUni ("}");
2356 WriteLine ("");
2360 void GenerateReadXmlNodeElement (XmlTypeMapping typeMap, string isNullable)
2362 WriteLine ("return " + GetReadXmlNode (typeMap.TypeData, false) + ";");
2365 void GenerateReadPrimitiveElement (XmlTypeMapping typeMap, string isNullable)
2367 WriteLine ("XmlQualifiedName t = GetXsiType();");
2368 WriteLine ("if (t == null) t = new XmlQualifiedName (" + GetLiteral(typeMap.XmlType) + ", " + GetLiteral(typeMap.Namespace) + ");");
2369 WriteLine ("return " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (t)") + ";");
2372 void GenerateReadEnumElement (XmlTypeMapping typeMap, string isNullable)
2374 WriteLine ("Reader.ReadStartElement ();");
2375 WriteLine (typeMap.TypeData.CSharpFullName + " res = " + GenerateGetEnumValue (typeMap, "Reader.ReadString()", false) + ";");
2376 WriteLineInd ("if (Reader.NodeType != XmlNodeType.None)");
2377 WriteLineUni ("Reader.ReadEndElement ();");
2378 WriteLine ("return res;");
2381 string GenerateGetEnumValue (XmlTypeMapping typeMap, string val, bool isNullable)
2383 if (isNullable)
2384 return "(" + val + ") != null ? " + GetGetEnumValueName (typeMap) + " (" + val + ") : (" + typeMap.TypeData.CSharpFullName + "?) null";
2385 else
2386 return GetGetEnumValueName (typeMap) + " (" + val + ")";
2389 void GenerateGetEnumValueMethod (XmlTypeMapping typeMap)
2391 string metName = GetGetEnumValueName (typeMap);
2392 EnumMap map = (EnumMap) typeMap.ObjectMap;
2394 if (map.IsFlags)
2396 string switchMethod = metName + "_Switch";
2397 WriteLine (typeMap.TypeData.CSharpFullName + " " + metName + " (string xmlName)");
2398 WriteLineInd ("{");
2399 WriteLine ("xmlName = xmlName.Trim();");
2400 WriteLine ("if (xmlName.Length == 0) return (" + typeMap.TypeData.CSharpFullName + ")0;");
2401 WriteLine (typeMap.TypeData.CSharpFullName + " sb = (" + typeMap.TypeData.CSharpFullName + ")0;");
2402 WriteLine ("string[] enumNames = xmlName.Split (null);");
2403 WriteLine ("foreach (string name in enumNames)");
2404 WriteLineInd ("{");
2405 WriteLine ("if (name == string.Empty) continue;");
2406 WriteLine ("sb |= " + switchMethod + " (name); ");
2407 WriteLineUni ("}");
2408 WriteLine ("return sb;");
2409 WriteLineUni ("}");
2410 WriteLine ("");
2411 metName = switchMethod;
2414 WriteLine (typeMap.TypeData.CSharpFullName + " " + metName + " (string xmlName)");
2415 WriteLineInd ("{");
2416 GenerateGetSingleEnumValue (typeMap, "xmlName");
2417 WriteLineUni ("}");
2418 WriteLine ("");
2421 void GenerateGetSingleEnumValue (XmlTypeMapping typeMap, string val)
2423 EnumMap map = (EnumMap) typeMap.ObjectMap;
2424 WriteLine ("switch (" + val + ")");
2425 WriteLineInd ("{");
2426 foreach (EnumMap.EnumMapMember mem in map.Members)
2428 WriteLine ("case " + GetLiteral (mem.XmlName) + ": return " + typeMap.TypeData.CSharpFullName + ".@" + mem.EnumName + ";");
2430 WriteLineInd ("default:");
2431 WriteLine ("throw CreateUnknownConstantException (" + val + ", typeof(" + typeMap.TypeData.CSharpFullName + "));");
2432 Unindent ();
2433 WriteLineUni ("}");
2436 void GenerateReadXmlSerializableElement (XmlTypeMapping typeMap, string isNullable)
2438 WriteLine ("Reader.MoveToContent ();");
2439 WriteLine ("if (Reader.NodeType == XmlNodeType.Element)");
2440 WriteLineInd ("{");
2441 WriteLine ("if (Reader.LocalName == " + GetLiteral (typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")");
2442 WriteLine (String.Format ("\treturn ({0}) ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true));", typeMap.TypeData.CSharpFullName));
2443 WriteLine ("else");
2444 WriteLine ("\tthrow CreateUnknownNodeException ();");
2445 WriteLineUni ("}");
2446 WriteLine ("else UnknownNode (null);");
2447 WriteLine ("");
2448 WriteLine ("return default (" + typeMap.TypeData.CSharpFullName + ");");
2451 void GenerateReadInitCallbacks ()
2453 WriteLine ("protected override void InitCallbacks ()");
2454 WriteLineInd ("{");
2456 if (_format == SerializationFormat.Encoded)
2458 foreach (XmlMapping xmap in _mapsToGenerate)
2460 XmlTypeMapping map = xmap as XmlTypeMapping;
2461 if (map == null) continue;
2462 if (map.TypeData.SchemaType == SchemaTypes.Class || map.TypeData.SchemaType == SchemaTypes.Enum)
2463 WriteMetCall ("AddReadCallback", GetLiteral (map.XmlType), GetLiteral(map.Namespace), GetTypeOf(map.TypeData.Type), "new XmlSerializationReadCallback (" + GetReadObjectName (map) + ")");
2467 WriteLineUni ("}");
2468 WriteLine ("");
2470 WriteLine ("protected override void InitIDs ()");
2471 WriteLine ("{");
2472 WriteLine ("}");
2473 WriteLine ("");
2476 void GenerateFixupCallbacks ()
2478 foreach (XmlMapping map in _fixupCallbacks)
2480 bool isList = map is XmlMembersMapping;
2481 string tname = !isList ? ((XmlTypeMapping)map).TypeData.CSharpFullName : "object[]";
2482 WriteLine ("void " + GetFixupCallbackName (map) + " (object obfixup)");
2483 WriteLineInd ("{");
2484 WriteLine ("Fixup fixup = (Fixup)obfixup;");
2485 WriteLine (tname + " source = (" + tname + ") fixup.Source;");
2486 WriteLine ("string[] ids = fixup.Ids;");
2487 WriteLine ("");
2489 ClassMap cmap = (ClassMap)map.ObjectMap;
2490 ICollection members = cmap.ElementMembers;
2491 if (members != null) {
2492 foreach (XmlTypeMapMember member in members)
2494 WriteLineInd ("if (ids[" + member.Index + "] != null)");
2495 string val = "GetTarget(ids[" + member.Index + "])";
2496 if (!isList) val = GetCast (member.TypeData, val);
2497 GenerateSetMemberValue (member, "source", val, isList);
2498 Unindent ();
2501 WriteLineUni ("}");
2502 WriteLine ("");
2506 string GetReadXmlNode (TypeData type, bool wrapped)
2508 if (type.Type == typeof (XmlDocument))
2509 return GetCast (type, TypeTranslator.GetTypeData (typeof(XmlDocument)), "ReadXmlDocument (" + GetLiteral(wrapped) + ")");
2510 else
2511 return GetCast (type, TypeTranslator.GetTypeData (typeof(XmlNode)), "ReadXmlNode (" + GetLiteral(wrapped) + ")");
2514 #endregion
2516 #region Helper methods
2518 //*******************************************************
2519 // Helper methods
2522 ArrayList _listsToFill = new ArrayList ();
2523 Hashtable _hookVariables;
2524 Stack _hookContexts;
2525 Stack _hookOpenHooks;
2527 class HookInfo {
2528 public HookType HookType;
2529 public Type Type;
2530 public string Member;
2531 public HookDir Direction;
2534 void InitHooks ()
2536 _hookContexts = new Stack ();
2537 _hookOpenHooks = new Stack ();
2538 _hookVariables = new Hashtable ();
2541 void PushHookContext ()
2543 _hookContexts.Push (_hookVariables);
2544 _hookVariables = (Hashtable) _hookVariables.Clone ();
2547 void PopHookContext ()
2549 _hookVariables = (Hashtable) _hookContexts.Pop ();
2552 void SetHookVar (string var, string value)
2554 _hookVariables [var] = value;
2557 bool GenerateReadHook (HookType hookType, Type type)
2559 return GenerateHook (hookType, HookDir.Read, type, null);
2562 bool GenerateWriteHook (HookType hookType, Type type)
2564 return GenerateHook (hookType, HookDir.Write, type, null);
2567 bool GenerateWriteMemberHook (Type type, XmlTypeMapMember member)
2569 SetHookVar ("$MEMBER", member.Name);
2570 return GenerateHook (HookType.member, HookDir.Write, type, member.Name);
2573 bool GenerateReadMemberHook (Type type, XmlTypeMapMember member)
2575 SetHookVar ("$MEMBER", member.Name);
2576 return GenerateHook (HookType.member, HookDir.Read, type, member.Name);
2579 bool GenerateReadArrayMemberHook (Type type, XmlTypeMapMember member, string index)
2581 SetHookVar ("$INDEX", index);
2582 return GenerateReadMemberHook (type, member);
2585 bool MemberHasReadReplaceHook (Type type, XmlTypeMapMember member)
2587 if (_config == null) return false;
2588 return _config.GetHooks (HookType.member, HookDir.Read, HookAction.Replace, type, member.Name).Count > 0;
2591 bool GenerateHook (HookType hookType, HookDir dir, Type type, string member)
2593 GenerateHooks (hookType, dir, type, null, HookAction.InsertBefore);
2594 if (GenerateHooks (hookType, dir, type, null, HookAction.Replace))
2596 GenerateHooks (hookType, dir, type, null, HookAction.InsertAfter);
2597 return true;
2599 else
2601 HookInfo hi = new HookInfo ();
2602 hi.HookType = hookType;
2603 hi.Type = type;
2604 hi.Member = member;
2605 hi.Direction = dir;
2606 _hookOpenHooks.Push (hi);
2607 return false;
2611 void GenerateEndHook ()
2613 HookInfo hi = (HookInfo) _hookOpenHooks.Pop();
2614 GenerateHooks (hi.HookType, hi.Direction, hi.Type, hi.Member, HookAction.InsertAfter);
2617 bool GenerateHooks (HookType hookType, HookDir dir, Type type, string member, HookAction action)
2619 if (_config == null) return false;
2620 ArrayList hooks = _config.GetHooks (hookType, dir, action, type, null);
2621 if (hooks.Count == 0) return false;
2622 foreach (Hook hook in hooks)
2624 string code = hook.GetCode (action);
2625 foreach (DictionaryEntry de in _hookVariables)
2626 code = code.Replace ((string)de.Key, (string)de.Value);
2627 WriteMultilineCode (code);
2629 return true;
2632 string GetRootTypeName ()
2634 if (_typeMap is XmlTypeMapping) return ((XmlTypeMapping)_typeMap).TypeData.CSharpFullName;
2635 else return "object[]";
2638 string GetNumTempVar ()
2640 return "n" + (_tempVarId++);
2643 string GetObTempVar ()
2645 return "o" + (_tempVarId++);
2648 string GetStrTempVar ()
2650 return "s" + (_tempVarId++);
2653 string GetBoolTempVar ()
2655 return "b" + (_tempVarId++);
2658 string GetUniqueName (string uniqueGroup, object ob, string name)
2660 name = CodeIdentifier.MakeValid (name.Replace ("[]","_array"));
2661 Hashtable names = (Hashtable) _uniqueNames [uniqueGroup];
2662 if (names == null) {
2663 names = new Hashtable ();
2664 _uniqueNames [uniqueGroup] = names;
2667 string res = (string) names [ob];
2668 if (res != null) return res;
2670 foreach (string n in names.Values)
2671 if (n == name) return GetUniqueName (uniqueGroup, ob, name + (_methodId++));
2673 names [ob] = name;
2674 return name;
2677 void RegisterReferencingMap (XmlTypeMapping typeMap)
2679 if (typeMap != null && !_mapsToGenerate.Contains (typeMap))
2680 _mapsToGenerate.Add (typeMap);
2683 string GetWriteObjectName (XmlTypeMapping typeMap)
2685 if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2686 return GetUniqueName ("rw", typeMap, "WriteObject_" + typeMap.XmlType);
2689 string GetReadObjectName (XmlTypeMapping typeMap)
2691 if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2692 return GetUniqueName ("rr", typeMap, "ReadObject_" + typeMap.XmlType);
2695 string GetGetEnumValueName (XmlTypeMapping typeMap)
2697 if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2698 return GetUniqueName ("ge", typeMap, "GetEnumValue_" + typeMap.XmlType);
2701 string GetWriteObjectCallbackName (XmlTypeMapping typeMap)
2703 if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2704 return GetUniqueName ("wc", typeMap, "WriteCallback_" + typeMap.XmlType);
2707 string GetFixupCallbackName (XmlMapping typeMap)
2709 if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2711 if (typeMap is XmlTypeMapping)
2712 return GetUniqueName ("fc", typeMap, "FixupCallback_" + ((XmlTypeMapping)typeMap).XmlType);
2713 else
2714 return GetUniqueName ("fc", typeMap, "FixupCallback__Message");
2717 string GetUniqueClassName (string s)
2719 return classNames.AddUnique (CodeIdentifier.MakeValid (s), null);
2722 string GetReadObjectCall (XmlTypeMapping typeMap, string isNullable, string checkType)
2724 if (_format == SerializationFormat.Literal)
2725 return GetReadObjectName (typeMap) + " (" + isNullable + ", " + checkType + ")";
2726 else
2727 return GetCast (typeMap.TypeData, GetReadObjectName (typeMap) + " ()");
2730 string GetFillListName (TypeData td)
2732 if (!_listsToFill.Contains (td)) _listsToFill.Add (td);
2733 return GetUniqueName ("fl", td, "Fill_" + CodeIdentifier.MakeValid (td.CSharpName));
2736 string GetCast (TypeData td, TypeData tdval, string val)
2738 if (td.CSharpFullName == tdval.CSharpFullName) return val;
2739 else return GetCast (td, val);
2742 string GetCast (TypeData td, string val)
2744 return "((" + td.CSharpFullName + ") " + val + ")";
2747 string GetCast (Type td, string val)
2749 return "((" + ToCSharpFullName (td) + ") " + val + ")";
2752 string GetTypeOf (TypeData td)
2754 return "typeof(" + td.CSharpFullName + ")";
2757 string GetTypeOf (Type td)
2759 return "typeof(" + ToCSharpFullName (td) + ")";
2762 string GetLiteral (object ob)
2764 if (ob == null) return "null";
2765 if (ob is string) return "\"" + ob.ToString().Replace("\"","\"\"") + "\"";
2766 if (ob is DateTime) return "new DateTime (" + ((DateTime) ob).Ticks + ")";
2767 #if NET_2_0
2768 if (ob is DateTimeOffset) return "new DateTimeOffset (" + ((DateTimeOffset) ob).Ticks + ")";
2769 #endif
2770 if (ob is TimeSpan) return "new TimeSpan (" + ((TimeSpan) ob).Ticks + ")";
2771 if (ob is bool) return ((bool)ob) ? "true" : "false";
2772 if (ob is XmlQualifiedName) {
2773 XmlQualifiedName qn = (XmlQualifiedName)ob;
2774 return "new XmlQualifiedName (" + GetLiteral(qn.Name) + "," + GetLiteral(qn.Namespace) + ")";
2776 if (ob is Enum) {
2777 string typeName = ToCSharpFullName (ob.GetType ());
2778 StringBuilder sb = new StringBuilder ();
2779 string namedValue = Enum.Format (ob.GetType (), ob, "g");
2780 string[] names = namedValue.Split (',');
2781 foreach (string name in names) {
2782 // individual named constants can be seperated by a comma
2783 // combined with some additional whitespace characters
2784 string cleanName = name.Trim ();
2785 if (cleanName.Length == 0)
2786 continue;
2788 if (sb.Length > 0)
2789 sb.Append (" | ");
2791 sb.Append (typeName);
2792 sb.Append ('.');
2793 sb.Append (cleanName);
2795 return sb.ToString ();
2798 return (ob is IFormattable) ? ((IFormattable) ob).ToString (null, CultureInfo.InvariantCulture) : ob.ToString ();
2801 void WriteLineInd (string code)
2803 WriteLine (code);
2804 _indent++;
2807 void WriteLineUni (string code)
2809 if (_indent > 0) _indent--;
2810 WriteLine (code);
2813 void Write (string code)
2815 if (code.Length > 0)
2816 _writer.Write (new String ('\t', _indent));
2817 _writer.Write (code);
2820 void WriteUni (string code)
2822 if (_indent > 0) _indent--;
2823 _writer.Write (code);
2824 _writer.WriteLine (string.Empty);
2827 void WriteLine (string code)
2829 if (code.Length > 0)
2830 _writer.Write (new String ('\t',_indent));
2831 _writer.WriteLine (code);
2834 void WriteMultilineCode (string code)
2836 string tabs = new string ('\t',_indent);
2837 code = code.Replace ("\r","");
2838 code = code.Replace ("\t","");
2839 while (code.StartsWith ("\n")) code = code.Substring (1);
2840 while (code.EndsWith ("\n")) code = code.Substring (0, code.Length - 1);
2841 code = code.Replace ("\n", "\n" + tabs);
2842 WriteLine (code);
2845 string Params (params string[] pars)
2847 string res = "";
2848 foreach (string p in pars)
2850 if (res != "") res += ", ";
2851 res += p;
2853 return res;
2856 void WriteMetCall (string method, params string[] pars)
2858 WriteLine (method + " (" + Params (pars) + ");");
2861 void Unindent ()
2863 _indent--;
2866 #endregion
2870 internal class GenerationResult
2872 public XmlMapping Mapping;
2873 public string ReaderClassName;
2874 public string ReadMethodName;
2875 public string WriterClassName;
2876 public string WriteMethodName;
2877 public string Namespace;
2878 #if NET_2_0
2879 public string SerializerClassName;
2880 #endif
2881 public string BaseSerializerClassName;
2882 public string ImplementationClassName;