XmlFormatWriterGenerator_static.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  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. // This check does not exist in the original dynamic code,
  143. // but there is no other way to check type mismatch.
  144. // CollectionSerialization.ArrayContract() shows that it is required.
  145. if (objLocal.GetType ().GetElementType () != itemType)
  146. throw new InvalidCastException (string.Format ("Cannot cast array of {0} to array of {1}", objLocal.GetType ().GetElementType (), itemType));
  147. ctx.IncrementArrayCount (writer, (Array) objLocal);
  148. if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, () => objLocal, itemName, itemNamespace))
  149. {
  150. var arr = (Array) objLocal;
  151. var idx = new int [1];
  152. for (i = 0; i < arr.Length; i++) {
  153. if (!TryWritePrimitive(itemType, null, null, i, itemNamespace, itemName, 0)) {
  154. WriteStartElement (itemType, collectionContract.Namespace, itemNamespace, itemName, 0);
  155. idx [0] = i;
  156. var mbrVal = arr.GetValue (idx);
  157. WriteValue (itemType, mbrVal, false);
  158. WriteEndElement ();
  159. }
  160. }
  161. }
  162. }
  163. else
  164. {
  165. // This check does not exist in the original dynamic code,
  166. // but there is no other way to check type mismatch.
  167. // CollectionSerialization.ArrayContract() shows that it is required.
  168. if (!collectionContract.UnderlyingType.IsAssignableFrom (objLocal.GetType ()))
  169. throw new InvalidCastException (string.Format ("Cannot cast {0} to {1}", objLocal.GetType (), collectionContract.UnderlyingType));
  170. MethodInfo incrementCollectionCountMethod = null;
  171. switch (collectionContract.Kind)
  172. {
  173. case CollectionKind.Collection:
  174. case CollectionKind.List:
  175. case CollectionKind.Dictionary:
  176. incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod;
  177. break;
  178. case CollectionKind.GenericCollection:
  179. case CollectionKind.GenericList:
  180. incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType);
  181. break;
  182. case CollectionKind.GenericDictionary:
  183. incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments()));
  184. break;
  185. }
  186. if (incrementCollectionCountMethod != null)
  187. incrementCollectionCountMethod.Invoke (ctx, new object [] {writer, objLocal});
  188. bool isDictionary = false, isGenericDictionary = false;
  189. Type enumeratorType = null;
  190. Type [] keyValueTypes = null;
  191. if (collectionContract.Kind == CollectionKind.GenericDictionary)
  192. {
  193. isGenericDictionary = true;
  194. keyValueTypes = collectionContract.ItemType.GetGenericArguments ();
  195. enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType (keyValueTypes);
  196. }
  197. else if (collectionContract.Kind == CollectionKind.Dictionary)
  198. {
  199. isDictionary = true;
  200. keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject };
  201. enumeratorType = Globals.TypeOfDictionaryEnumerator;
  202. }
  203. else
  204. {
  205. enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType;
  206. }
  207. MethodInfo moveNextMethod = enumeratorType.GetMethod (Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
  208. MethodInfo getCurrentMethod = enumeratorType.GetMethod (Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
  209. if (moveNextMethod == null || getCurrentMethod == null)
  210. {
  211. if (enumeratorType.IsInterface)
  212. {
  213. if (moveNextMethod == null)
  214. moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod;
  215. if (getCurrentMethod == null)
  216. getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod;
  217. }
  218. else
  219. {
  220. Type ienumeratorInterface = Globals.TypeOfIEnumerator;
  221. CollectionKind kind = collectionContract.Kind;
  222. if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable)
  223. {
  224. Type[] interfaceTypes = enumeratorType.GetInterfaces();
  225. foreach (Type interfaceType in interfaceTypes)
  226. {
  227. if (interfaceType.IsGenericType
  228. && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric
  229. && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType)
  230. {
  231. ienumeratorInterface = interfaceType;
  232. break;
  233. }
  234. }
  235. }
  236. if (moveNextMethod == null)
  237. moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface);
  238. if (getCurrentMethod == null)
  239. getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface);
  240. }
  241. }
  242. Type elementType = getCurrentMethod.ReturnType;
  243. object currentValue = null; // of elementType
  244. var enumerator = (IEnumerator) collectionContract.GetEnumeratorMethod.Invoke (objLocal, new object [0]);
  245. if (isDictionary)
  246. {
  247. enumerator = new CollectionDataContract.DictionaryEnumerator ((IDictionaryEnumerator) enumerator);
  248. }
  249. else if (isGenericDictionary)
  250. {
  251. Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes));
  252. ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null);
  253. enumerator = (IEnumerator) Activator.CreateInstance (enumeratorType, new object [] {enumerator});
  254. }
  255. var emptyArray = new object [0];
  256. while (enumerator != null && enumerator.MoveNext ()) {
  257. currentValue = getCurrentMethod.Invoke (enumerator, emptyArray);
  258. if (incrementCollectionCountMethod == null)
  259. XmlFormatGeneratorStatics.IncrementItemCountMethod.Invoke (ctx, new object [] {1});
  260. if (!TryWritePrimitive (elementType, () => currentValue, null, null, itemNamespace, itemName, 0))
  261. {
  262. WriteStartElement (elementType, collectionContract.Namespace, itemNamespace, itemName, 0);
  263. if (isGenericDictionary || isDictionary)
  264. collectionDataContract.ItemContract.WriteXmlValue (writer, currentValue, ctx);
  265. else
  266. WriteValue (elementType, currentValue, false);
  267. WriteEndElement();
  268. }
  269. }
  270. }
  271. }
  272. int WriteMembers (ClassDataContract classContract, ExtensionDataObject extensionData, ClassDataContract derivedMostClassContract)
  273. {
  274. int memberCount = (classContract.BaseContract == null) ? 0 : WriteMembers (classContract.BaseContract, extensionData, derivedMostClassContract);
  275. XmlDictionaryString ns =
  276. (contractNamespaces == null) ? dataContract.Namespace :
  277. contractNamespaces [typeIndex - 1];
  278. ctx.IncrementItemCount (classContract.Members.Count);
  279. for (int i = 0; i < classContract.Members.Count; i++, memberCount++) {
  280. DataMember member = classContract.Members[i];
  281. Type memberType = member.MemberType;
  282. object memberValue = null;
  283. if (member.IsGetOnlyCollection)
  284. ctx.StoreIsGetOnlyCollection ();
  285. bool doWrite = true, hasMemberValue = false;
  286. if (!member.EmitDefaultValue)
  287. {
  288. hasMemberValue = true;
  289. memberValue = LoadMemberValue (member);
  290. doWrite = !IsDefaultValue (memberType, memberValue);
  291. }
  292. if (doWrite) {
  293. bool writeXsiType = CheckIfMemberHasConflict (member, classContract, derivedMostClassContract);
  294. if (writeXsiType || !TryWritePrimitive (memberType, hasMemberValue ? () => memberValue : (Func<object>) null, member.MemberInfo, null /*arrayItemIndex*/, ns, null /*nameLocal*/, i + childElementIndex)) {
  295. WriteStartElement (memberType, classContract.Namespace, ns, null /*nameLocal*/, i + childElementIndex);
  296. if (classContract.ChildElementNamespaces [i + childElementIndex] != null)
  297. writer.WriteNamespaceDecl (childElementNamespaces [i + childElementIndex]);
  298. if (memberValue == null)
  299. memberValue = LoadMemberValue (member);
  300. WriteValue (memberType, memberValue, writeXsiType);
  301. WriteEndElement ();
  302. }
  303. if (classContract.HasExtensionData)
  304. ctx.WriteExtensionData (writer, extensionData, memberCount);
  305. } else if (!member.EmitDefaultValue) {
  306. if (member.IsRequired)
  307. XmlObjectSerializerWriteContext.ThrowRequiredMemberMustBeEmitted (member.Name, classContract.UnderlyingType);
  308. }
  309. }
  310. typeIndex++;
  311. childElementIndex += classContract.Members.Count;
  312. return memberCount;
  313. }
  314. internal bool IsDefaultValue (Type type, object value)
  315. {
  316. return GetDefaultValue (type).Equals (value);
  317. }
  318. internal object GetDefaultValue(Type type)
  319. {
  320. if (type.IsValueType)
  321. {
  322. switch (Type.GetTypeCode(type))
  323. {
  324. case TypeCode.Boolean:
  325. return false;
  326. case TypeCode.Char:
  327. case TypeCode.SByte:
  328. case TypeCode.Byte:
  329. case TypeCode.Int16:
  330. case TypeCode.UInt16:
  331. case TypeCode.Int32:
  332. case TypeCode.UInt32:
  333. return 0;
  334. case TypeCode.Int64:
  335. case TypeCode.UInt64:
  336. return 0L;
  337. case TypeCode.Single:
  338. return 0.0F;
  339. case TypeCode.Double:
  340. return 0.0;
  341. case TypeCode.Decimal:
  342. return default (decimal);
  343. case TypeCode.DateTime:
  344. return default (DateTime);
  345. }
  346. }
  347. return null;
  348. }
  349. bool CheckIfMemberHasConflict(DataMember member, ClassDataContract classContract, ClassDataContract derivedMostClassContract)
  350. {
  351. // Check for conflict with base type members
  352. if (CheckIfConflictingMembersHaveDifferentTypes(member))
  353. return true;
  354. // Check for conflict with derived type members
  355. string name = member.Name;
  356. string ns = classContract.StableName.Namespace;
  357. ClassDataContract currentContract = derivedMostClassContract;
  358. while (currentContract != null && currentContract != classContract)
  359. {
  360. if (ns == currentContract.StableName.Namespace)
  361. {
  362. List<DataMember> members = currentContract.Members;
  363. for (int j = 0; j < members.Count; j++)
  364. {
  365. if (name == members[j].Name)
  366. return CheckIfConflictingMembersHaveDifferentTypes(members[j]);
  367. }
  368. }
  369. currentContract = currentContract.BaseContract;
  370. }
  371. return false;
  372. }
  373. bool CheckIfConflictingMembersHaveDifferentTypes(DataMember member)
  374. {
  375. while (member.ConflictingMember != null)
  376. {
  377. if (member.MemberType != member.ConflictingMember.MemberType)
  378. return true;
  379. member = member.ConflictingMember;
  380. }
  381. return false;
  382. }
  383. bool NeedsPrefix(Type type, XmlDictionaryString ns)
  384. {
  385. return type == Globals.TypeOfXmlQualifiedName && (ns != null && ns.Value != null && ns.Value.Length > 0);
  386. }
  387. void WriteStartElement (Type type, XmlDictionaryString ns, XmlDictionaryString namespaceLocal, XmlDictionaryString nameLocal, int nameIndex)
  388. {
  389. bool needsPrefix = NeedsPrefix(type, ns);
  390. nameLocal = nameLocal ?? memberNames [nameIndex];
  391. if (needsPrefix)
  392. writer.WriteStartElement (Globals.ElementPrefix, nameLocal, namespaceLocal);
  393. else
  394. writer.WriteStartElement (nameLocal, namespaceLocal);
  395. }
  396. void WriteEndElement ()
  397. {
  398. writer.WriteEndElement ();
  399. }
  400. void WriteValue (Type memberType, object memberValue, bool writeXsiType)
  401. {
  402. Pointer memberValueRefPointer = null;
  403. if (memberType.IsPointer)
  404. memberValueRefPointer = (Pointer) XmlFormatGeneratorStatics.BoxPointer.Invoke (null, new object [] {memberValue, memberType});
  405. bool isNullableOfT = (memberType.IsGenericType &&
  406. memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable);
  407. if (memberType.IsValueType && !isNullableOfT)
  408. {
  409. PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
  410. if (primitiveContract != null && !writeXsiType)
  411. primitiveContract.XmlFormatContentWriterMethod.Invoke (writer, new object [] {memberValue});
  412. else
  413. InternalSerialize(XmlFormatGeneratorStatics.InternalSerializeMethod, () => memberValue, memberType, writeXsiType);
  414. }
  415. else
  416. {
  417. bool isNull;
  418. if (isNullableOfT)
  419. memberValue = UnwrapNullableObject(() => memberValue, ref memberType, out isNull); //Leaves !HasValue on stack
  420. else
  421. isNull = memberValue == null;
  422. if (isNull)
  423. XmlFormatGeneratorStatics.WriteNullMethod.Invoke (ctx, new object [] {writer, memberType, DataContract.IsTypeSerializable(memberType)});
  424. else {
  425. PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
  426. if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject && !writeXsiType) {
  427. if (isNullableOfT)
  428. primitiveContract.XmlFormatContentWriterMethod.Invoke (writer, new object [] {memberValue});
  429. else
  430. primitiveContract.XmlFormatContentWriterMethod.Invoke (ctx, new object [] {writer, memberValue});
  431. } else {
  432. bool isNull2 = false;
  433. if (memberType == Globals.TypeOfObject || //boxed Nullable<T>
  434. memberType == Globals.TypeOfValueType ||
  435. ((IList)Globals.TypeOfNullable.GetInterfaces()).Contains(memberType)) {
  436. var unwrappedMemberValue = CodeInterpreter.ConvertValue (memberValue, memberType.GetType (), Globals.TypeOfObject);
  437. memberValue = unwrappedMemberValue;
  438. isNull2 = memberValue == null;
  439. }
  440. if (isNull2) {
  441. XmlFormatGeneratorStatics.WriteNullMethod.Invoke (ctx, new object [] {writer, memberType, DataContract.IsTypeSerializable(memberType)});
  442. } else {
  443. InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod),
  444. () => memberValue, memberType, writeXsiType);
  445. }
  446. }
  447. }
  448. }
  449. }
  450. void InternalSerialize (MethodInfo methodInfo, Func<object> memberValue, Type memberType, bool writeXsiType)
  451. {
  452. var v = memberValue ();
  453. var typeHandleValue = Type.GetTypeHandle (v);
  454. var isDeclaredType = typeHandleValue.Equals (CodeInterpreter.ConvertValue (v, memberType, Globals.TypeOfObject));
  455. methodInfo.Invoke (ctx, new object [] {writer, memberValue != null ? v : null, isDeclaredType, writeXsiType, DataContract.GetId (memberType.TypeHandle), memberType.TypeHandle});
  456. }
  457. object UnwrapNullableObject(Func<object> memberValue, ref Type memberType, out bool isNull)// Leaves !HasValue on stack
  458. {
  459. object v = memberValue ();
  460. isNull = false;
  461. while (memberType.IsGenericType && memberType.GetGenericTypeDefinition () == Globals.TypeOfNullable) {
  462. Type innerType = memberType.GetGenericArguments () [0];
  463. if ((bool) XmlFormatGeneratorStatics.GetHasValueMethod.MakeGenericMethod (innerType).Invoke (null, new object [] {v}))
  464. v = XmlFormatGeneratorStatics.GetNullableValueMethod.MakeGenericMethod (innerType).Invoke (null, new object [] {v});
  465. else {
  466. isNull = true;
  467. v = XmlFormatGeneratorStatics.GetDefaultValueMethod.MakeGenericMethod (memberType).Invoke (null, new object [0]);
  468. }
  469. memberType = innerType;
  470. }
  471. return v;
  472. }
  473. bool TryWritePrimitive(Type type, Func<object> value, MemberInfo memberInfo, int? arrayItemIndex, XmlDictionaryString ns, XmlDictionaryString name, int nameIndex)
  474. {
  475. PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type);
  476. if (primitiveContract == null || primitiveContract.UnderlyingType == Globals.TypeOfObject)
  477. return false;
  478. object callee = null;
  479. var args = new List<object> ();
  480. // load xmlwriter
  481. if (type.IsValueType)
  482. callee = writer;
  483. else {
  484. callee = ctx;
  485. args.Add (writer);
  486. }
  487. // load primitive value
  488. if (value != null)
  489. args.Add (value ());
  490. else if (memberInfo != null)
  491. args.Add (CodeInterpreter.GetMember (memberInfo, objLocal));
  492. else
  493. args.Add (((Array) objLocal).GetValue (new int [] {(int) arrayItemIndex}));
  494. // load name
  495. if (name != null)
  496. args.Add (name);
  497. else
  498. args.Add (memberNames [nameIndex]);
  499. // load namespace
  500. args.Add (ns);
  501. // call method to write primitive
  502. primitiveContract.XmlFormatWriterMethod.Invoke (callee, args.ToArray ());
  503. return true;
  504. }
  505. bool TryWritePrimitiveArray (Type type, Type itemType, Func<object> value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
  506. {
  507. PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(itemType);
  508. if (primitiveContract == null)
  509. return false;
  510. string writeArrayMethod = null;
  511. switch (Type.GetTypeCode(itemType))
  512. {
  513. case TypeCode.Boolean:
  514. writeArrayMethod = "WriteBooleanArray";
  515. break;
  516. case TypeCode.DateTime:
  517. writeArrayMethod = "WriteDateTimeArray";
  518. break;
  519. case TypeCode.Decimal:
  520. writeArrayMethod = "WriteDecimalArray";
  521. break;
  522. case TypeCode.Int32:
  523. writeArrayMethod = "WriteInt32Array";
  524. break;
  525. case TypeCode.Int64:
  526. writeArrayMethod = "WriteInt64Array";
  527. break;
  528. case TypeCode.Single:
  529. writeArrayMethod = "WriteSingleArray";
  530. break;
  531. case TypeCode.Double:
  532. writeArrayMethod = "WriteDoubleArray";
  533. break;
  534. default:
  535. break;
  536. }
  537. if (writeArrayMethod != null)
  538. {
  539. typeof (XmlWriterDelegator).GetMethod (writeArrayMethod, Globals.ScanAllMembers, null, new Type[] { type, typeof (XmlDictionaryString), typeof (XmlDictionaryString) }, null).Invoke (writer, new object [] {value (), itemName, itemNamespace});
  540. return true;
  541. }
  542. return false;
  543. }
  544. object LoadMemberValue (DataMember member)
  545. {
  546. return CodeInterpreter.GetMember (member.MemberInfo, objLocal);
  547. }
  548. }
  549. }