XmlFormatWriterGenerator_static.cs 22 KB

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