[S.R.Serialization] do not update memberType when not expected.
[mono.git] / mcs / class / System.Runtime.Serialization / ReferenceSources / XmlFormatWriterGenerator_static.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Reflection;
6 using System.Xml;
7
8 namespace System.Runtime.Serialization
9 {
10         internal partial class XmlFormatWriterGenerator
11         {
12                 partial class CriticalHelper
13                 {
14                         internal XmlFormatClassWriterDelegate GenerateClassWriter(ClassDataContract classContract)
15                         {
16                                 return (XmlWriterDelegator xw, object obj, XmlObjectSerializerWriteContext ctx, ClassDataContract ctr) => new XmlFormatWriterInterpreter (classContract).WriteToXml (xw, obj, ctx, ctr);
17                         }
18
19                         internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract)
20                         {
21                                 return (XmlWriterDelegator xw, object obj, XmlObjectSerializerWriteContext ctx, CollectionDataContract ctr) => new XmlFormatWriterInterpreter (collectionContract).WriteCollectionToXml (xw, obj, ctx, ctr);
22                         }
23                 }
24         }
25
26         class XmlFormatWriterInterpreter
27         {
28                 public XmlFormatWriterInterpreter (ClassDataContract classContract)
29                 {
30                         this.classContract = classContract;
31                 }
32
33                 public XmlFormatWriterInterpreter (CollectionDataContract collectionContract)
34                 {
35                         this.collectionContract = collectionContract;
36                 }
37
38                 ClassDataContract classContract;
39
40                 CollectionDataContract collectionContract;
41
42                 XmlWriterDelegator writer = null;
43                 object obj = null;
44                 XmlObjectSerializerWriteContext ctx = null;
45                 DataContract dataContract = null;
46                 object objLocal = null;
47
48                 ClassDataContract classDataContract {
49                         get { return (ClassDataContract) dataContract; }
50                 }
51                 CollectionDataContract collectionDataContract {
52                         get {return (CollectionDataContract) dataContract; }
53                 }
54
55                 XmlDictionaryString [] contractNamespaces = null;
56                 XmlDictionaryString [] memberNames = null;
57                 XmlDictionaryString [] childElementNamespaces = null;
58                 int typeIndex = 1;
59                 int childElementIndex = 0;
60
61                 public void WriteToXml (XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, ClassDataContract dataContract)
62                 {
63                         this.writer = xmlWriter;
64                         this.obj = obj;
65                         this.ctx = context;
66                         this.dataContract = dataContract;
67
68                         InitArgs (classContract.UnderlyingType);
69
70                         // DemandSerializationFormatterPermission (classContract) - irrelevant
71                         // DemandMemberAccessPermission (memberAccessFlag) - irrelevant
72
73                         if (classContract.IsReadOnlyContract)
74                         {
75                                 DataContract.ThrowInvalidDataContractException (classContract.SerializationExceptionMessage, null);
76                         }
77
78                         WriteClass (classContract);
79                 }
80
81                 public void WriteCollectionToXml (XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, CollectionDataContract collectionContract)
82                 {
83                         this.writer = xmlWriter;
84                         this.obj = obj;
85                         this.ctx = context;
86                         this.dataContract = collectionContract;
87
88                         InitArgs (collectionContract.UnderlyingType);                   
89
90                         // DemandMemberAccessPermission(memberAccessFlag);
91                         if (collectionContract.IsReadOnlyContract)
92                         {
93                                 DataContract.ThrowInvalidDataContractException (collectionContract.SerializationExceptionMessage, null);
94                         }
95
96                         WriteCollection (collectionContract);
97                 }
98
99                 void InitArgs (Type objType)
100                 {
101                         if (objType == Globals.TypeOfDateTimeOffsetAdapter) {
102                                 objLocal = DateTimeOffsetAdapter.GetDateTimeOffsetAdapter ((DateTimeOffset) obj);
103                         }
104                         else
105                                 objLocal = CodeInterpreter.ConvertValue (obj, typeof (object), objType);
106                 }
107
108                 void InvokeOnSerializing (ClassDataContract classContract, object objSerialized, XmlObjectSerializerWriteContext ctx)
109                 {
110                         if (classContract.BaseContract != null)
111                                 InvokeOnSerializing (classContract.BaseContract, objSerialized, ctx);
112                         if (classContract.OnSerializing != null) {
113                                 classContract.OnSerializing.Invoke (objSerialized, new object [] {ctx.GetStreamingContext ()});
114                         }
115                 }
116
117                 void InvokeOnSerialized (ClassDataContract classContract, object objSerialized, XmlObjectSerializerWriteContext ctx)
118                 {
119                         if (classContract.BaseContract != null)
120                                 InvokeOnSerialized (classContract.BaseContract, objSerialized, ctx);
121                         if (classContract.OnSerialized != null) {
122                                 classContract.OnSerialized.Invoke (objSerialized, new object [] {ctx.GetStreamingContext ()});
123                         }
124                 }
125
126                 void WriteClass (ClassDataContract classContract)
127                 {
128                         InvokeOnSerializing (classContract, objLocal, ctx);
129
130                         if (classContract.IsISerializable)
131                                 ctx.WriteISerializable (writer, (ISerializable) objLocal);
132                         else
133                         {
134                                 if (classContract.ContractNamespaces.Length > 1)
135                                         contractNamespaces = classDataContract.ContractNamespaces;
136                                 memberNames = classDataContract.MemberNames;
137
138                                 for (int i = 0; i < classContract.ChildElementNamespaces.Length; i++)
139                                 {
140                                         if (classContract.ChildElementNamespaces[i] != null)
141                                         {
142                                                 childElementNamespaces = classDataContract.ChildElementNamespaces;
143                                         }
144                                 }
145
146                                 if (classContract.HasExtensionData)
147                                 {
148                                         ExtensionDataObject extensionData = ((IExtensibleDataObject) objLocal).ExtensionData;
149                                         ctx.WriteExtensionData (writer, extensionData, -1);
150
151                                         WriteMembers (classContract, extensionData, classContract);
152                                 }
153                                 else
154                                         WriteMembers (classContract, null, classContract);
155                         }
156                         InvokeOnSerialized (classContract, objLocal, ctx);
157                 }
158
159                 void WriteCollection(CollectionDataContract collectionContract)
160                 {
161                         XmlDictionaryString itemNamespace = dataContract.Namespace;
162
163                         XmlDictionaryString itemName = collectionDataContract.CollectionItemName;
164
165                         if (collectionContract.ChildElementNamespace != null)
166                                 writer.WriteNamespaceDecl (collectionDataContract.ChildElementNamespace);
167
168                         if (collectionContract.Kind == CollectionKind.Array)
169                         {
170                                 Type itemType = collectionContract.ItemType;
171                                 int i;
172                                 ctx.IncrementArrayCount (writer, (Array) objLocal);
173
174                                 if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, () => objLocal, itemName, itemNamespace))
175                                 {
176                                         var arr = (Array) objLocal;
177                                         var idx = new int [1];
178                                         for (i = 0; i < arr.Length; i++) {
179                                                 if (!TryWritePrimitive(itemType, null, null, i, itemNamespace, itemName, 0)) {
180                                                         WriteStartElement (itemType, collectionContract.Namespace, itemNamespace, itemName, 0);
181                                                         idx [0] = i;
182                                                         var mbrVal = arr.GetValue (idx);
183                                                         WriteValue (itemType, mbrVal, false);
184                                                         WriteEndElement ();
185                                                 }
186                                         }
187                                 }
188                         }
189                         else
190                         {
191                                 MethodInfo incrementCollectionCountMethod = null;
192                                 switch (collectionContract.Kind)
193                                 {
194                                 case CollectionKind.Collection:
195                                 case CollectionKind.List:
196                                 case CollectionKind.Dictionary:
197                                         incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod;
198                                         break;
199                                 case CollectionKind.GenericCollection:
200                                 case CollectionKind.GenericList:
201                                         incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType);
202                                         break;
203                                 case CollectionKind.GenericDictionary:
204                                         incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments()));
205                                         break;
206                                 }
207                                 if (incrementCollectionCountMethod != null)
208                                         incrementCollectionCountMethod.Invoke (ctx, new object [] {writer, objLocal});
209
210                                 bool isDictionary = false, isGenericDictionary = false;
211                                 Type enumeratorType = null;
212                                 Type [] keyValueTypes = null;
213                                 if (collectionContract.Kind == CollectionKind.GenericDictionary)
214                                 {
215                                         isGenericDictionary = true;
216                                         keyValueTypes = collectionContract.ItemType.GetGenericArguments ();
217                                         enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType (keyValueTypes);
218                                 }
219                                 else if (collectionContract.Kind == CollectionKind.Dictionary)
220                                 {
221                                         isDictionary = true;
222                                         keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject };
223                                         enumeratorType = Globals.TypeOfDictionaryEnumerator;
224                                 }
225                                 else
226                                 {
227                                         enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType;
228                                 }
229                                 MethodInfo moveNextMethod = enumeratorType.GetMethod (Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
230                                 MethodInfo getCurrentMethod = enumeratorType.GetMethod (Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
231                                 if (moveNextMethod == null || getCurrentMethod == null)
232                                 {
233                                         if (enumeratorType.IsInterface)
234                                         {
235                                                 if (moveNextMethod == null)
236                                                         moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod;
237                                                 if (getCurrentMethod == null)
238                                                         getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod;
239                                         }
240                                         else
241                                         {
242                                                 Type ienumeratorInterface = Globals.TypeOfIEnumerator;
243                                                 CollectionKind kind = collectionContract.Kind;
244                                                 if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable)
245                                                 {
246                                                         Type[] interfaceTypes = enumeratorType.GetInterfaces();
247                                                         foreach (Type interfaceType in interfaceTypes)
248                                                         {
249                                                                 if (interfaceType.IsGenericType
250                                                                         && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric
251                                                                         && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType)
252                                                                 {
253                                                                         ienumeratorInterface = interfaceType;
254                                                                         break;
255                                                                 }
256                                                         }
257                                                 }
258                                                 if (moveNextMethod == null)
259                                                         moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface);
260                                                 if (getCurrentMethod == null)
261                                                         getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface);
262                                         }
263                                 }
264                                 Type elementType = getCurrentMethod.ReturnType;
265                                 object currentValue = null; // of elementType
266
267                                 var enumerator = (IEnumerator) collectionContract.GetEnumeratorMethod.Invoke (objLocal, new object [0]);
268                                 if (isDictionary)
269                                 {
270                                         enumerator = new CollectionDataContract.DictionaryEnumerator ((IDictionaryEnumerator) enumerator);
271                                 }
272                                 else if (isGenericDictionary)
273                                 {
274                                         Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes));
275                                         ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null);
276                                         enumerator = (IEnumerator) Activator.CreateInstance (enumeratorType, new object [] {enumerator});
277                                 }
278
279                                 var emptyArray = new object [0];
280                                 while (enumerator != null && enumerator.MoveNext ()) {
281                                         currentValue = getCurrentMethod.Invoke (enumerator, emptyArray);
282
283                                         if (incrementCollectionCountMethod == null)
284                                                 XmlFormatGeneratorStatics.IncrementItemCountMethod.Invoke (ctx, new object [] {1});
285
286                                         if (!TryWritePrimitive (elementType, () => currentValue, null, null, itemNamespace, itemName, 0))
287                                         {
288                                                 WriteStartElement (elementType, collectionContract.Namespace, itemNamespace, itemName, 0);
289                                                 if (isGenericDictionary || isDictionary)
290                                                         collectionDataContract.ItemContract.WriteXmlValue (writer, currentValue, ctx);
291                                                 else
292                                                         WriteValue (elementType, currentValue, false);
293                                                 WriteEndElement();
294                                         }
295                                 }
296                         }
297                 }
298
299                 int WriteMembers (ClassDataContract classContract, ExtensionDataObject extensionData, ClassDataContract derivedMostClassContract)
300                 {
301                         int memberCount = (classContract.BaseContract == null) ? 0 : WriteMembers (classContract.BaseContract, extensionData, derivedMostClassContract);
302
303                         XmlDictionaryString ns = 
304                                 (contractNamespaces == null) ? dataContract.Namespace :
305                                 contractNamespaces [typeIndex - 1];
306
307                         ctx.IncrementItemCount (classContract.Members.Count);
308
309                         for (int i = 0; i < classContract.Members.Count; i++, memberCount++) {
310
311                                 DataMember member = classContract.Members[i];
312                                 Type memberType = member.MemberType;
313                                 object memberValue = null;
314                                 if (member.IsGetOnlyCollection)
315                                         ctx.StoreIsGetOnlyCollection ();
316                                 bool doWrite = true, hasMemberValue = false;
317                                 if (!member.EmitDefaultValue)
318                                 {
319                                         hasMemberValue = true;
320                                         memberValue = LoadMemberValue (member);
321                                         doWrite = !IsDefaultValue (memberType, memberValue);
322                                 }
323
324                                 if (doWrite) {
325
326                                         bool writeXsiType = CheckIfMemberHasConflict (member, classContract, derivedMostClassContract);
327                                         if (writeXsiType || !TryWritePrimitive (memberType, hasMemberValue ? () => memberValue : (Func<object>) null, member.MemberInfo, null /*arrayItemIndex*/, ns, null /*nameLocal*/, i + childElementIndex)) {
328                                                 WriteStartElement (memberType, classContract.Namespace, ns, null /*nameLocal*/, i + childElementIndex);
329                                                 if (classContract.ChildElementNamespaces [i + childElementIndex] != null)
330                                                         writer.WriteNamespaceDecl (childElementNamespaces [i + childElementIndex]);
331                                                 if (memberValue == null)
332                                                         memberValue = LoadMemberValue (member);
333                                                 WriteValue (memberType, memberValue, writeXsiType);
334                                                 WriteEndElement ();
335                                         }
336
337                                         if (classContract.HasExtensionData)
338                                                 ctx.WriteExtensionData (writer, extensionData, memberCount);
339                                 } else if (!member.EmitDefaultValue) {
340                                         if (member.IsRequired)
341                                                 XmlObjectSerializerWriteContext.ThrowRequiredMemberMustBeEmitted (member.Name, classContract.UnderlyingType);
342                                 }
343                         }
344
345                         typeIndex++;
346                         childElementIndex += classContract.Members.Count;
347                         return memberCount;
348                 }
349
350
351                 internal bool IsDefaultValue (Type type, object value)
352                 {
353                         return GetDefaultValue (type).Equals (value);
354                 }
355
356                 internal object GetDefaultValue(Type type)
357                 {
358                         if (type.IsValueType)
359                         {
360                                 switch (Type.GetTypeCode(type))
361                                 {
362                                 case TypeCode.Boolean:
363                                         return false;
364                                 case TypeCode.Char:
365                                 case TypeCode.SByte:
366                                 case TypeCode.Byte:
367                                 case TypeCode.Int16:
368                                 case TypeCode.UInt16:
369                                 case TypeCode.Int32:
370                                 case TypeCode.UInt32:
371                                         return 0;
372                                 case TypeCode.Int64:
373                                 case TypeCode.UInt64:
374                                         return 0L;
375                                 case TypeCode.Single:
376                                         return 0.0F;
377                                 case TypeCode.Double:
378                                         return 0.0;
379                                 case TypeCode.Decimal:
380                                         return default (decimal);
381                                 case TypeCode.DateTime:
382                                         return default (DateTime);
383                                 }
384                         }
385                         return null;
386                 }
387
388                 bool CheckIfMemberHasConflict(DataMember member, ClassDataContract classContract, ClassDataContract derivedMostClassContract)
389                 {
390                         // Check for conflict with base type members
391                         if (CheckIfConflictingMembersHaveDifferentTypes(member))
392                                 return true;
393
394                         // Check for conflict with derived type members
395                         string name = member.Name;
396                         string ns = classContract.StableName.Namespace;
397                         ClassDataContract currentContract = derivedMostClassContract;
398                         while (currentContract != null && currentContract != classContract)
399                         {
400                                 if (ns == currentContract.StableName.Namespace)
401                                 {
402                                         List<DataMember> members = currentContract.Members;
403                                         for (int j = 0; j < members.Count; j++)
404                                         {
405                                                 if (name == members[j].Name)
406                                                         return CheckIfConflictingMembersHaveDifferentTypes(members[j]);
407                                         }
408                                 }
409                                 currentContract = currentContract.BaseContract;
410                         }
411
412                         return false;
413                 }
414
415                 bool CheckIfConflictingMembersHaveDifferentTypes(DataMember member)
416                 {
417                         while (member.ConflictingMember != null)
418                         {
419                                 if (member.MemberType != member.ConflictingMember.MemberType)
420                                         return true;
421                                 member = member.ConflictingMember;
422                         }
423                         return false;
424                 }
425
426                 bool NeedsPrefix(Type type, XmlDictionaryString ns)
427                 {
428                         return type == Globals.TypeOfXmlQualifiedName && (ns != null && ns.Value != null && ns.Value.Length > 0);
429                 }
430
431                 void WriteStartElement (Type type, XmlDictionaryString ns, XmlDictionaryString namespaceLocal, XmlDictionaryString nameLocal, int nameIndex)
432                 {
433                         bool needsPrefix = NeedsPrefix(type, ns);
434                         nameLocal = nameLocal ?? memberNames [nameIndex];
435                         if (needsPrefix)
436                                 writer.WriteStartElement (Globals.ElementPrefix, nameLocal, namespaceLocal);
437                         else
438                                 writer.WriteStartElement (nameLocal, namespaceLocal);
439                 }
440
441                 void WriteEndElement ()
442                 {
443                         writer.WriteEndElement ();
444                 }
445
446                 void WriteValue (Type memberType, object memberValue, bool writeXsiType)
447                 {
448                         Pointer memberValueRefPointer = null;
449                         if (memberType.IsPointer)
450                                 memberValueRefPointer = (Pointer) XmlFormatGeneratorStatics.BoxPointer.Invoke (null, new object [] {memberValue, memberType});
451                         bool isNullableOfT = (memberType.IsGenericType &&
452                                 memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable);
453                         if (memberType.IsValueType && !isNullableOfT)
454                         {
455                                 PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
456                                 if (primitiveContract != null && !writeXsiType)
457                                         primitiveContract.XmlFormatContentWriterMethod.Invoke (writer, new object [] {memberValue});
458                                 else
459                                         InternalSerialize(XmlFormatGeneratorStatics.InternalSerializeMethod, () => memberValue, memberType, writeXsiType);
460                         }
461                         else
462                         {
463                                 bool isNull;
464                                 if (isNullableOfT)
465                                         memberValue = UnwrapNullableObject(() => memberValue, ref memberType, out isNull); //Leaves !HasValue on stack
466                                 else
467                                         isNull = memberValue == null;
468                                 if (isNull)
469                                         XmlFormatGeneratorStatics.WriteNullMethod.Invoke (ctx, new object [] {writer, memberType, DataContract.IsTypeSerializable(memberType)});
470                                 else {
471                                         PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
472                                         if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject && !writeXsiType) {
473                                                 if (isNullableOfT)
474                                                         primitiveContract.XmlFormatContentWriterMethod.Invoke (writer, new object [] {memberValue});
475                                                 else                                                    
476                                                         primitiveContract.XmlFormatContentWriterMethod.Invoke (ctx, new object [] {writer, memberValue});
477                                         } else {
478                                                 bool isNull2 = false;
479                                                 if (memberType == Globals.TypeOfObject || //boxed Nullable<T>
480                                                         memberType == Globals.TypeOfValueType ||
481                                                         ((IList)Globals.TypeOfNullable.GetInterfaces()).Contains(memberType)) {
482                                                         var unwrappedMemberValue = CodeInterpreter.ConvertValue (memberValue, memberType.GetType (), Globals.TypeOfObject);
483                                                         memberValue = unwrappedMemberValue;
484                                                         isNull2 = memberValue == null;
485                                                 }
486                                                 if (isNull2) {
487                                                         XmlFormatGeneratorStatics.WriteNullMethod.Invoke (ctx, new object [] {writer, memberType, DataContract.IsTypeSerializable(memberType)});
488                                                 } else {
489                                                         InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod),
490                                                                 () => memberValue, memberType, writeXsiType);
491                                                 }
492                                         }
493                                 }
494                         }
495                 }
496
497                 void InternalSerialize (MethodInfo methodInfo, Func<object> memberValue, Type memberType, bool writeXsiType)
498                 {
499                         var v = memberValue ();
500                         var typeHandleValue = Type.GetTypeHandle (v);
501                         var isDeclaredType = typeHandleValue.Equals (CodeInterpreter.ConvertValue (v, memberType, Globals.TypeOfObject));
502                         methodInfo.Invoke (ctx, new object [] {writer, memberValue != null ? v : null, isDeclaredType, writeXsiType, DataContract.GetId (memberType.TypeHandle), memberType.TypeHandle});
503                 }
504
505                 object UnwrapNullableObject(Func<object> memberValue, ref Type memberType, out bool isNull)// Leaves !HasValue on stack
506                 {
507                         object v = memberValue ();
508                         isNull = false;
509                         while (memberType.IsGenericType && memberType.GetGenericTypeDefinition () == Globals.TypeOfNullable) {
510                                 Type innerType = memberType.GetGenericArguments () [0];
511                                 if ((bool) XmlFormatGeneratorStatics.GetHasValueMethod.MakeGenericMethod (innerType).Invoke (null, new object [] {v}))
512                                         v = XmlFormatGeneratorStatics.GetNullableValueMethod.MakeGenericMethod (innerType).Invoke (null, new object [] {v});
513                                 else {
514                                         isNull = true;
515                                         v = XmlFormatGeneratorStatics.GetDefaultValueMethod.MakeGenericMethod (memberType).Invoke (null, new object [0]);
516                                 }
517                                 memberType = innerType;
518                         }
519                         
520                         return v;
521                 }
522
523                 bool TryWritePrimitive(Type type, Func<object> value, MemberInfo memberInfo, int? arrayItemIndex, XmlDictionaryString ns, XmlDictionaryString name, int nameIndex)
524                 {
525                         PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type);
526                         if (primitiveContract == null || primitiveContract.UnderlyingType == Globals.TypeOfObject)
527                                 return false;
528
529                         object callee = null;
530                         var args = new List<object> ();
531
532                         // load xmlwriter
533                         if (type.IsValueType)
534                                 callee = writer;
535                         else {
536                                 callee = ctx;
537                                 args.Add (writer);
538                         }
539                         // load primitive value 
540                         if (value != null)
541                                 args.Add (value ());
542                         else if (memberInfo != null)
543                                 args.Add (CodeInterpreter.GetMember (memberInfo, objLocal));
544                         else
545                                 args.Add (((Array) objLocal).GetValue (new int [] {(int) arrayItemIndex}));
546                         // load name
547                         if (name != null)
548                                 args.Add (name);
549                         else {
550                                 if (memberNames.Length <= nameIndex) throw new Exception (string.Format ("@@@@@@@@@@@@@@@@@@@ {0} {1} ({2}/{3})", type, memberInfo, nameIndex, memberNames.Length));
551                                 args.Add (memberNames [nameIndex]);
552                         }
553                         // load namespace
554                         args.Add (ns);
555                         // call method to write primitive
556                         primitiveContract.XmlFormatWriterMethod.Invoke (callee, args.ToArray ());
557                         return true;
558                 }
559
560                 bool TryWritePrimitiveArray (Type type, Type itemType, Func<object> value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
561                 {
562                         PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(itemType);
563                         if (primitiveContract == null)
564                                 return false;
565
566                         string writeArrayMethod = null;
567                         switch (Type.GetTypeCode(itemType))
568                         {
569                         case TypeCode.Boolean:
570                                 writeArrayMethod = "WriteBooleanArray";
571                                 break;
572                         case TypeCode.DateTime:
573                                 writeArrayMethod = "WriteDateTimeArray";
574                                 break;
575                         case TypeCode.Decimal:
576                                 writeArrayMethod = "WriteDecimalArray";
577                                 break;
578                         case TypeCode.Int32:
579                                 writeArrayMethod = "WriteInt32Array";
580                                 break;
581                         case TypeCode.Int64:
582                                 writeArrayMethod = "WriteInt64Array";
583                                 break;
584                         case TypeCode.Single:
585                                 writeArrayMethod = "WriteSingleArray";
586                                 break;
587                         case TypeCode.Double:
588                                 writeArrayMethod = "WriteDoubleArray";
589                                 break;
590                         default:
591                                 break;
592                         }
593                         if (writeArrayMethod != null)
594                         {
595                                 typeof (XmlWriterDelegator).GetMethod (writeArrayMethod, Globals.ScanAllMembers, null, new Type[] { type, typeof (XmlDictionaryString), typeof (XmlDictionaryString) }, null).Invoke (writer, new object [] {value (), itemName, itemNamespace});
596                                 return true;
597                         }
598                         return false;
599                 }
600
601                 object LoadMemberValue (DataMember member)
602                 {
603                         return CodeInterpreter.GetMember (member.MemberInfo, objLocal);
604                 }
605         }
606 }