PageRenderTime 59ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/Lesql/Dependencies/ServiceStack.Text/JsConfig.cs

https://bitbucket.org/kbrekke/lesql
C# | 1095 lines | 824 code | 133 blank | 138 comment | 124 complexity | 41262afbba755a29427ba0ff5f21e098 MD5 | raw file
  1. using InternalDependency.ServiceStack.Text.Common;
  2. using InternalDependency.ServiceStack.Text.Json;
  3. using InternalDependency.ServiceStack.Text.Jsv;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Reflection;
  8. #if WINDOWS_PHONE && !WP8
  9. using ServiceStack.Text.WP;
  10. #endif
  11. namespace InternalDependency.ServiceStack.Text
  12. {
  13. public static class
  14. JsConfig
  15. {
  16. static JsConfig()
  17. {
  18. //In-built default serialization, to Deserialize Color struct do:
  19. //JsConfig<System.Drawing.Color>.SerializeFn = c => c.ToString().Replace("Color ", "").Replace("[", "").Replace("]", "");
  20. //JsConfig<System.Drawing.Color>.DeSerializeFn = System.Drawing.Color.FromName;
  21. Reset();
  22. }
  23. public static JsConfigScope BeginScope()
  24. {
  25. return new JsConfigScope();
  26. }
  27. public static JsConfigScope With(
  28. bool? convertObjectTypesIntoStringDictionary = null,
  29. bool? tryToParsePrimitiveTypeValues = null,
  30. bool? tryToParseNumericType = null,
  31. bool? includeNullValues = null,
  32. bool? excludeTypeInfo = null,
  33. bool? includeTypeInfo = null,
  34. bool? emitCamelCaseNames = null,
  35. bool? emitLowercaseUnderscoreNames = null,
  36. JsonDateHandler? dateHandler = null,
  37. JsonTimeSpanHandler? timeSpanHandler = null,
  38. bool? preferInterfaces = null,
  39. bool? throwOnDeserializationError = null,
  40. string typeAttr = null,
  41. Func<Type, string> typeWriter = null,
  42. Func<string, Type> typeFinder = null,
  43. bool? treatEnumAsInteger = null,
  44. bool? alwaysUseUtc = null,
  45. bool? assumeUtc = null,
  46. bool? appendUtcOffset = null,
  47. bool? escapeUnicode = null,
  48. bool? includePublicFields = null,
  49. int? maxDepth = null,
  50. EmptyCtorFactoryDelegate modelFactory = null,
  51. string[] excludePropertyReferences = null)
  52. {
  53. return new JsConfigScope
  54. {
  55. ConvertObjectTypesIntoStringDictionary = convertObjectTypesIntoStringDictionary ?? sConvertObjectTypesIntoStringDictionary,
  56. TryToParsePrimitiveTypeValues = tryToParsePrimitiveTypeValues ?? sTryToParsePrimitiveTypeValues,
  57. TryToParseNumericType = tryToParseNumericType ?? sTryToParseNumericType,
  58. IncludeNullValues = includeNullValues ?? sIncludeNullValues,
  59. ExcludeTypeInfo = excludeTypeInfo ?? sExcludeTypeInfo,
  60. IncludeTypeInfo = includeTypeInfo ?? sIncludeTypeInfo,
  61. EmitCamelCaseNames = emitCamelCaseNames ?? sEmitCamelCaseNames,
  62. EmitLowercaseUnderscoreNames = emitLowercaseUnderscoreNames ?? sEmitLowercaseUnderscoreNames,
  63. DateHandler = dateHandler ?? sDateHandler,
  64. TimeSpanHandler = timeSpanHandler ?? sTimeSpanHandler,
  65. PreferInterfaces = preferInterfaces ?? sPreferInterfaces,
  66. ThrowOnDeserializationError = throwOnDeserializationError ?? sThrowOnDeserializationError,
  67. TypeAttr = typeAttr ?? sTypeAttr,
  68. TypeWriter = typeWriter ?? sTypeWriter,
  69. TypeFinder = typeFinder ?? sTypeFinder,
  70. TreatEnumAsInteger = treatEnumAsInteger ?? sTreatEnumAsInteger,
  71. AlwaysUseUtc = alwaysUseUtc ?? sAlwaysUseUtc,
  72. AssumeUtc = assumeUtc ?? sAssumeUtc,
  73. AppendUtcOffset = appendUtcOffset ?? sAppendUtcOffset,
  74. EscapeUnicode = escapeUnicode ?? sEscapeUnicode,
  75. IncludePublicFields = includePublicFields ?? sIncludePublicFields,
  76. MaxDepth = maxDepth ?? sMaxDepth,
  77. ModelFactory = modelFactory ?? ModelFactory,
  78. ExcludePropertyReferences = excludePropertyReferences ?? sExcludePropertyReferences
  79. };
  80. }
  81. private static bool? sConvertObjectTypesIntoStringDictionary;
  82. public static bool ConvertObjectTypesIntoStringDictionary
  83. {
  84. get
  85. {
  86. return (JsConfigScope.Current != null ? JsConfigScope.Current.ConvertObjectTypesIntoStringDictionary : null)
  87. ?? sConvertObjectTypesIntoStringDictionary
  88. ?? false;
  89. }
  90. set
  91. {
  92. if (!sConvertObjectTypesIntoStringDictionary.HasValue) sConvertObjectTypesIntoStringDictionary = value;
  93. }
  94. }
  95. private static bool? sTryToParsePrimitiveTypeValues;
  96. public static bool TryToParsePrimitiveTypeValues
  97. {
  98. get
  99. {
  100. return (JsConfigScope.Current != null ? JsConfigScope.Current.TryToParsePrimitiveTypeValues : null)
  101. ?? sTryToParsePrimitiveTypeValues
  102. ?? false;
  103. }
  104. set
  105. {
  106. if (!sTryToParsePrimitiveTypeValues.HasValue) sTryToParsePrimitiveTypeValues = value;
  107. }
  108. }
  109. private static bool? sTryToParseNumericType;
  110. public static bool TryToParseNumericType
  111. {
  112. get
  113. {
  114. return (JsConfigScope.Current != null ? JsConfigScope.Current.TryToParseNumericType : null)
  115. ?? sTryToParseNumericType
  116. ?? false;
  117. }
  118. set
  119. {
  120. if (!sTryToParseNumericType.HasValue) sTryToParseNumericType = value;
  121. }
  122. }
  123. private static bool? sIncludeNullValues;
  124. public static bool IncludeNullValues
  125. {
  126. get
  127. {
  128. return (JsConfigScope.Current != null ? JsConfigScope.Current.IncludeNullValues : null)
  129. ?? sIncludeNullValues
  130. ?? false;
  131. }
  132. set
  133. {
  134. if (!sIncludeNullValues.HasValue) sIncludeNullValues = value;
  135. }
  136. }
  137. private static bool? sTreatEnumAsInteger;
  138. public static bool TreatEnumAsInteger
  139. {
  140. get
  141. {
  142. return (JsConfigScope.Current != null ? JsConfigScope.Current.TreatEnumAsInteger : null)
  143. ?? sTreatEnumAsInteger
  144. ?? false;
  145. }
  146. set
  147. {
  148. if (!sTreatEnumAsInteger.HasValue) sTreatEnumAsInteger = value;
  149. }
  150. }
  151. private static bool? sExcludeTypeInfo;
  152. public static bool ExcludeTypeInfo
  153. {
  154. get
  155. {
  156. return (JsConfigScope.Current != null ? JsConfigScope.Current.ExcludeTypeInfo : null)
  157. ?? sExcludeTypeInfo
  158. ?? false;
  159. }
  160. set
  161. {
  162. if (!sExcludeTypeInfo.HasValue) sExcludeTypeInfo = value;
  163. }
  164. }
  165. private static bool? sIncludeTypeInfo;
  166. public static bool IncludeTypeInfo
  167. {
  168. get
  169. {
  170. return (JsConfigScope.Current != null ? JsConfigScope.Current.IncludeTypeInfo : null)
  171. ?? sIncludeTypeInfo
  172. ?? false;
  173. }
  174. set
  175. {
  176. if (!sIncludeTypeInfo.HasValue) sIncludeTypeInfo = value;
  177. }
  178. }
  179. private static string sTypeAttr;
  180. public static string TypeAttr
  181. {
  182. get
  183. {
  184. return (JsConfigScope.Current != null ? JsConfigScope.Current.TypeAttr : null)
  185. ?? sTypeAttr
  186. ?? JsWriter.TypeAttr;
  187. }
  188. set
  189. {
  190. if (sTypeAttr == null) sTypeAttr = value;
  191. JsonTypeAttrInObject = JsonTypeSerializer.GetTypeAttrInObject(value);
  192. JsvTypeAttrInObject = JsvTypeSerializer.GetTypeAttrInObject(value);
  193. }
  194. }
  195. private static string sJsonTypeAttrInObject;
  196. private static readonly string defaultJsonTypeAttrInObject = JsonTypeSerializer.GetTypeAttrInObject(TypeAttr);
  197. internal static string JsonTypeAttrInObject
  198. {
  199. get
  200. {
  201. return (JsConfigScope.Current != null ? JsConfigScope.Current.JsonTypeAttrInObject : null)
  202. ?? sJsonTypeAttrInObject
  203. ?? defaultJsonTypeAttrInObject;
  204. }
  205. set
  206. {
  207. if (sJsonTypeAttrInObject == null) sJsonTypeAttrInObject = value;
  208. }
  209. }
  210. private static string sJsvTypeAttrInObject;
  211. private static readonly string defaultJsvTypeAttrInObject = JsvTypeSerializer.GetTypeAttrInObject(TypeAttr);
  212. internal static string JsvTypeAttrInObject
  213. {
  214. get
  215. {
  216. return (JsConfigScope.Current != null ? JsConfigScope.Current.JsvTypeAttrInObject : null)
  217. ?? sJsvTypeAttrInObject
  218. ?? defaultJsvTypeAttrInObject;
  219. }
  220. set
  221. {
  222. if (sJsvTypeAttrInObject == null) sJsvTypeAttrInObject = value;
  223. }
  224. }
  225. private static Func<Type, string> sTypeWriter;
  226. public static Func<Type, string> TypeWriter
  227. {
  228. get
  229. {
  230. return (JsConfigScope.Current != null ? JsConfigScope.Current.TypeWriter : null)
  231. ?? sTypeWriter
  232. ?? AssemblyUtils.WriteType;
  233. }
  234. set
  235. {
  236. if (sTypeWriter == null) sTypeWriter = value;
  237. }
  238. }
  239. private static Func<string, Type> sTypeFinder;
  240. public static Func<string, Type> TypeFinder
  241. {
  242. get
  243. {
  244. return (JsConfigScope.Current != null ? JsConfigScope.Current.TypeFinder : null)
  245. ?? sTypeFinder
  246. ?? AssemblyUtils.FindType;
  247. }
  248. set
  249. {
  250. if (sTypeFinder == null) sTypeFinder = value;
  251. }
  252. }
  253. private static JsonDateHandler? sDateHandler;
  254. public static JsonDateHandler DateHandler
  255. {
  256. get
  257. {
  258. return (JsConfigScope.Current != null ? JsConfigScope.Current.DateHandler : null)
  259. ?? sDateHandler
  260. ?? JsonDateHandler.TimestampOffset;
  261. }
  262. set
  263. {
  264. if (!sDateHandler.HasValue) sDateHandler = value;
  265. }
  266. }
  267. /// <summary>
  268. /// Sets which format to use when serializing TimeSpans
  269. /// </summary>
  270. private static JsonTimeSpanHandler? sTimeSpanHandler;
  271. public static JsonTimeSpanHandler TimeSpanHandler
  272. {
  273. get
  274. {
  275. return (JsConfigScope.Current != null ? JsConfigScope.Current.TimeSpanHandler : null)
  276. ?? sTimeSpanHandler
  277. ?? JsonTimeSpanHandler.DurationFormat;
  278. }
  279. set
  280. {
  281. if (!sTimeSpanHandler.HasValue) sTimeSpanHandler = value;
  282. }
  283. }
  284. /// <summary>
  285. /// <see langword="true"/> if the <see cref="ITypeSerializer"/> is configured
  286. /// to take advantage of <see cref="CLSCompliantAttribute"/> specification,
  287. /// to support user-friendly serialized formats, ie emitting camelCasing for JSON
  288. /// and parsing member names and enum values in a case-insensitive manner.
  289. /// </summary>
  290. private static bool? sEmitCamelCaseNames;
  291. public static bool EmitCamelCaseNames
  292. {
  293. // obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
  294. get
  295. {
  296. return (JsConfigScope.Current != null ? JsConfigScope.Current.EmitCamelCaseNames : null)
  297. ?? sEmitCamelCaseNames
  298. ?? false;
  299. }
  300. set
  301. {
  302. if (!sEmitCamelCaseNames.HasValue) sEmitCamelCaseNames = value;
  303. }
  304. }
  305. /// <summary>
  306. /// <see langword="true"/> if the <see cref="ITypeSerializer"/> is configured
  307. /// to support web-friendly serialized formats, ie emitting lowercase_underscore_casing for JSON
  308. /// </summary>
  309. private static bool? sEmitLowercaseUnderscoreNames;
  310. public static bool EmitLowercaseUnderscoreNames
  311. {
  312. // obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
  313. get
  314. {
  315. return (JsConfigScope.Current != null ? JsConfigScope.Current.EmitLowercaseUnderscoreNames : null)
  316. ?? sEmitLowercaseUnderscoreNames
  317. ?? false;
  318. }
  319. set
  320. {
  321. if (!sEmitLowercaseUnderscoreNames.HasValue) sEmitLowercaseUnderscoreNames = value;
  322. }
  323. }
  324. /// <summary>
  325. /// Define how property names are mapped during deserialization
  326. /// </summary>
  327. private static JsonPropertyConvention propertyConvention;
  328. public static JsonPropertyConvention PropertyConvention
  329. {
  330. get { return propertyConvention; }
  331. set
  332. {
  333. propertyConvention = value;
  334. switch (propertyConvention)
  335. {
  336. case JsonPropertyConvention.ExactMatch:
  337. DeserializeTypeRefJson.PropertyNameResolver = DeserializeTypeRefJson.DefaultPropertyNameResolver;
  338. break;
  339. case JsonPropertyConvention.Lenient:
  340. DeserializeTypeRefJson.PropertyNameResolver = DeserializeTypeRefJson.LenientPropertyNameResolver;
  341. break;
  342. }
  343. }
  344. }
  345. /// <summary>
  346. /// Gets or sets a value indicating if the framework should throw serialization exceptions
  347. /// or continue regardless of deserialization errors. If <see langword="true"/> the framework
  348. /// will throw; otherwise, it will parse as many fields as possible. The default is <see langword="false"/>.
  349. /// </summary>
  350. private static bool? sThrowOnDeserializationError;
  351. public static bool ThrowOnDeserializationError
  352. {
  353. // obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
  354. get
  355. {
  356. return (JsConfigScope.Current != null ? JsConfigScope.Current.ThrowOnDeserializationError : null)
  357. ?? sThrowOnDeserializationError
  358. ?? false;
  359. }
  360. set
  361. {
  362. if (!sThrowOnDeserializationError.HasValue) sThrowOnDeserializationError = value;
  363. }
  364. }
  365. /// <summary>
  366. /// Gets or sets a value indicating if the framework should always convert <see cref="DateTime"/> to UTC format instead of local time.
  367. /// </summary>
  368. private static bool? sAlwaysUseUtc;
  369. public static bool AlwaysUseUtc
  370. {
  371. // obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
  372. get
  373. {
  374. return (JsConfigScope.Current != null ? JsConfigScope.Current.AlwaysUseUtc : null)
  375. ?? sAlwaysUseUtc
  376. ?? false;
  377. }
  378. set
  379. {
  380. if (!sAlwaysUseUtc.HasValue) sAlwaysUseUtc = value;
  381. }
  382. }
  383. /// <summary>
  384. /// Gets or sets a value indicating if the framework should always assume <see cref="DateTime"/> is in UTC format if Kind is Unspecified.
  385. /// </summary>
  386. private static bool? sAssumeUtc;
  387. public static bool AssumeUtc
  388. {
  389. // obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
  390. get
  391. {
  392. return (JsConfigScope.Current != null ? JsConfigScope.Current.AssumeUtc : null)
  393. ?? sAssumeUtc
  394. ?? false;
  395. }
  396. set
  397. {
  398. if (!sAssumeUtc.HasValue) sAssumeUtc = value;
  399. }
  400. }
  401. /// <summary>
  402. /// Gets or sets whether we should append the Utc offset when we serialize Utc dates. Defaults to no.
  403. /// Only supported for when the JsConfig.DateHandler == JsonDateHandler.TimestampOffset
  404. /// </summary>
  405. private static bool? sAppendUtcOffset;
  406. public static bool? AppendUtcOffset
  407. {
  408. // obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
  409. get
  410. {
  411. return (JsConfigScope.Current != null ? JsConfigScope.Current.AppendUtcOffset : null)
  412. ?? sAppendUtcOffset
  413. ?? null;
  414. }
  415. set
  416. {
  417. if (sAppendUtcOffset == null) sAppendUtcOffset = value;
  418. }
  419. }
  420. /// <summary>
  421. /// Gets or sets a value indicating if unicode symbols should be serialized as "\uXXXX".
  422. /// </summary>
  423. private static bool? sEscapeUnicode;
  424. public static bool EscapeUnicode
  425. {
  426. // obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
  427. get
  428. {
  429. return (JsConfigScope.Current != null ? JsConfigScope.Current.EscapeUnicode : null)
  430. ?? sEscapeUnicode
  431. ?? false;
  432. }
  433. set
  434. {
  435. if (!sEscapeUnicode.HasValue) sEscapeUnicode = value;
  436. }
  437. }
  438. internal static HashSet<Type> HasSerializeFn = new HashSet<Type>();
  439. public static HashSet<Type> TreatValueAsRefTypes = new HashSet<Type>();
  440. private static bool? sPreferInterfaces;
  441. /// <summary>
  442. /// If set to true, Interface types will be prefered over concrete types when serializing.
  443. /// </summary>
  444. public static bool PreferInterfaces
  445. {
  446. get
  447. {
  448. return (JsConfigScope.Current != null ? JsConfigScope.Current.PreferInterfaces : null)
  449. ?? sPreferInterfaces
  450. ?? false;
  451. }
  452. set
  453. {
  454. if (!sPreferInterfaces.HasValue) sPreferInterfaces = value;
  455. }
  456. }
  457. internal static bool TreatAsRefType(Type valueType)
  458. {
  459. return TreatValueAsRefTypes.Contains(valueType.IsGeneric() ? valueType.GenericTypeDefinition() : valueType);
  460. }
  461. /// <summary>
  462. /// If set to true, Interface types will be prefered over concrete types when serializing.
  463. /// </summary>
  464. private static bool? sIncludePublicFields;
  465. public static bool IncludePublicFields
  466. {
  467. get
  468. {
  469. return (JsConfigScope.Current != null ? JsConfigScope.Current.IncludePublicFields : null)
  470. ?? sIncludePublicFields
  471. ?? false;
  472. }
  473. set
  474. {
  475. if (!sIncludePublicFields.HasValue) sIncludePublicFields = value;
  476. }
  477. }
  478. /// <summary>
  479. /// Sets the maximum depth to avoid circular dependencies
  480. /// </summary>
  481. private static int? sMaxDepth;
  482. public static int MaxDepth
  483. {
  484. get
  485. {
  486. return (JsConfigScope.Current != null ? JsConfigScope.Current.MaxDepth : null)
  487. ?? sMaxDepth
  488. ?? int.MaxValue;
  489. }
  490. set
  491. {
  492. if (!sMaxDepth.HasValue) sMaxDepth = value;
  493. }
  494. }
  495. /// <summary>
  496. /// Set this to enable your own type construction provider.
  497. /// This is helpful for integration with IoC containers where you need to call the container constructor.
  498. /// Return null if you don't know how to construct the type and the parameterless constructor will be used.
  499. /// </summary>
  500. private static EmptyCtorFactoryDelegate sModelFactory;
  501. public static EmptyCtorFactoryDelegate ModelFactory
  502. {
  503. get
  504. {
  505. return (JsConfigScope.Current != null ? JsConfigScope.Current.ModelFactory : null)
  506. ?? sModelFactory
  507. ?? null;
  508. }
  509. set
  510. {
  511. if (sModelFactory != null) sModelFactory = value;
  512. }
  513. }
  514. private static string[] sExcludePropertyReferences;
  515. public static string[] ExcludePropertyReferences
  516. {
  517. get
  518. {
  519. return (JsConfigScope.Current != null ? JsConfigScope.Current.ExcludePropertyReferences : null)
  520. ?? sExcludePropertyReferences;
  521. }
  522. set
  523. {
  524. if (sExcludePropertyReferences != null) sExcludePropertyReferences = value;
  525. }
  526. }
  527. private static HashSet<Type> sExcludeTypes;
  528. public static HashSet<Type> ExcludeTypes
  529. {
  530. get
  531. {
  532. return (JsConfigScope.Current != null ? JsConfigScope.Current.ExcludeTypes : null)
  533. ?? sExcludeTypes;
  534. }
  535. set
  536. {
  537. if (sExcludePropertyReferences != null) sExcludeTypes = value;
  538. }
  539. }
  540. public static void Reset()
  541. {
  542. foreach (var rawSerializeType in HasSerializeFn.ToArray())
  543. {
  544. Reset(rawSerializeType);
  545. }
  546. foreach (var uniqueType in __uniqueTypes.ToArray())
  547. {
  548. Reset(uniqueType);
  549. }
  550. sModelFactory = ReflectionExtensions.GetConstructorMethodToCache;
  551. sTryToParsePrimitiveTypeValues = null;
  552. sTryToParseNumericType = null;
  553. sConvertObjectTypesIntoStringDictionary = null;
  554. sIncludeNullValues = null;
  555. sExcludeTypeInfo = null;
  556. sEmitCamelCaseNames = null;
  557. sEmitLowercaseUnderscoreNames = null;
  558. sDateHandler = null;
  559. sTimeSpanHandler = null;
  560. sPreferInterfaces = null;
  561. sThrowOnDeserializationError = null;
  562. sTypeAttr = null;
  563. sJsonTypeAttrInObject = null;
  564. sJsvTypeAttrInObject = null;
  565. sTypeWriter = null;
  566. sTypeFinder = null;
  567. sTreatEnumAsInteger = null;
  568. sAlwaysUseUtc = null;
  569. sAssumeUtc = null;
  570. sAppendUtcOffset = null;
  571. sEscapeUnicode = null;
  572. sIncludePublicFields = null;
  573. HasSerializeFn = new HashSet<Type>();
  574. TreatValueAsRefTypes = new HashSet<Type> { typeof(KeyValuePair<,>) };
  575. PropertyConvention = JsonPropertyConvention.ExactMatch;
  576. sExcludePropertyReferences = null;
  577. sExcludeTypes = new HashSet<Type> { typeof(Stream) };
  578. __uniqueTypes = new HashSet<Type>();
  579. sMaxDepth = 50;
  580. }
  581. private static void Reset(Type cachesForType)
  582. {
  583. typeof(JsConfig<>).MakeGenericType(new[] { cachesForType }).InvokeReset();
  584. typeof(TypeConfig<>).MakeGenericType(new[] { cachesForType }).InvokeReset();
  585. }
  586. internal static void InvokeReset(this Type genericType)
  587. {
  588. #if NETFX_CORE
  589. MethodInfo methodInfo = genericType.GetTypeInfo().GetType().GetMethodInfo("Reset");
  590. methodInfo.Invoke(null, null);
  591. #else
  592. var methodInfo = genericType.GetMethod("Reset", BindingFlags.Static | BindingFlags.Public);
  593. methodInfo.Invoke(null, null);
  594. #endif
  595. }
  596. #if MONOTOUCH
  597. /// <summary>
  598. /// Provide hint to MonoTouch AOT compiler to pre-compile generic classes for all your DTOs.
  599. /// Just needs to be called once in a static constructor.
  600. /// </summary>
  601. [MonoTouch.Foundation.Preserve]
  602. public static void InitForAot() {
  603. }
  604. [MonoTouch.Foundation.Preserve]
  605. public static void RegisterForAot()
  606. {
  607. RegisterTypeForAot<Poco>();
  608. RegisterElement<Poco, string>();
  609. RegisterElement<Poco, bool>();
  610. RegisterElement<Poco, char>();
  611. RegisterElement<Poco, byte>();
  612. RegisterElement<Poco, sbyte>();
  613. RegisterElement<Poco, short>();
  614. RegisterElement<Poco, ushort>();
  615. RegisterElement<Poco, int>();
  616. RegisterElement<Poco, uint>();
  617. RegisterElement<Poco, long>();
  618. RegisterElement<Poco, ulong>();
  619. RegisterElement<Poco, float>();
  620. RegisterElement<Poco, double>();
  621. RegisterElement<Poco, decimal>();
  622. RegisterElement<Poco, bool?>();
  623. RegisterElement<Poco, char?>();
  624. RegisterElement<Poco, byte?>();
  625. RegisterElement<Poco, sbyte?>();
  626. RegisterElement<Poco, short?>();
  627. RegisterElement<Poco, ushort?>();
  628. RegisterElement<Poco, int?>();
  629. RegisterElement<Poco, uint?>();
  630. RegisterElement<Poco, long?>();
  631. RegisterElement<Poco, ulong?>();
  632. RegisterElement<Poco, float?>();
  633. RegisterElement<Poco, double?>();
  634. RegisterElement<Poco, decimal?>();
  635. //RegisterElement<Poco, JsonValue>();
  636. RegisterTypeForAot<DayOfWeek>(); // used by DateTime
  637. // register built in structs
  638. RegisterTypeForAot<Guid>();
  639. RegisterTypeForAot<TimeSpan>();
  640. RegisterTypeForAot<DateTime>();
  641. RegisterTypeForAot<DateTime?>();
  642. RegisterTypeForAot<TimeSpan?>();
  643. RegisterTypeForAot<Guid?>();
  644. }
  645. [MonoTouch.Foundation.Preserve]
  646. public static void RegisterTypeForAot<T>()
  647. {
  648. AotConfig.RegisterSerializers<T>();
  649. }
  650. [MonoTouch.Foundation.Preserve]
  651. static void RegisterQueryStringWriter()
  652. {
  653. var i = 0;
  654. if (QueryStringWriter<Poco>.WriteFn() != null) i++;
  655. }
  656. [MonoTouch.Foundation.Preserve]
  657. internal static int RegisterElement<T, TElement>()
  658. {
  659. var i = 0;
  660. i += AotConfig.RegisterSerializers<TElement>();
  661. AotConfig.RegisterElement<T, TElement, JsonTypeSerializer>();
  662. AotConfig.RegisterElement<T, TElement, JsvTypeSerializer>();
  663. return i;
  664. }
  665. ///<summary>
  666. /// Class contains Ahead-of-Time (AOT) explicit class declarations which is used only to workaround "-aot-only" exceptions occured on device only.
  667. /// </summary>
  668. [MonoTouch.Foundation.Preserve(AllMembers=true)]
  669. internal class AotConfig
  670. {
  671. internal static JsReader<JsonTypeSerializer> jsonReader;
  672. internal static JsWriter<JsonTypeSerializer> jsonWriter;
  673. internal static JsReader<JsvTypeSerializer> jsvReader;
  674. internal static JsWriter<JsvTypeSerializer> jsvWriter;
  675. internal static JsonTypeSerializer jsonSerializer;
  676. internal static JsvTypeSerializer jsvSerializer;
  677. static AotConfig()
  678. {
  679. jsonSerializer = new JsonTypeSerializer();
  680. jsvSerializer = new JsvTypeSerializer();
  681. jsonReader = new JsReader<JsonTypeSerializer>();
  682. jsonWriter = new JsWriter<JsonTypeSerializer>();
  683. jsvReader = new JsReader<JsvTypeSerializer>();
  684. jsvWriter = new JsWriter<JsvTypeSerializer>();
  685. }
  686. internal static int RegisterSerializers<T>()
  687. {
  688. var i = 0;
  689. i += Register<T, JsonTypeSerializer>();
  690. if (jsonSerializer.GetParseFn<T>() != null) i++;
  691. if (jsonSerializer.GetWriteFn<T>() != null) i++;
  692. if (jsonReader.GetParseFn<T>() != null) i++;
  693. if (jsonWriter.GetWriteFn<T>() != null) i++;
  694. i += Register<T, JsvTypeSerializer>();
  695. if (jsvSerializer.GetParseFn<T>() != null) i++;
  696. if (jsvSerializer.GetWriteFn<T>() != null) i++;
  697. if (jsvReader.GetParseFn<T>() != null) i++;
  698. if (jsvWriter.GetWriteFn<T>() != null) i++;
  699. //RegisterCsvSerializer<T>();
  700. RegisterQueryStringWriter();
  701. return i;
  702. }
  703. internal static void RegisterCsvSerializer<T>()
  704. {
  705. CsvSerializer<T>.WriteFn();
  706. CsvSerializer<T>.WriteObject(null, null);
  707. CsvWriter<T>.Write(null, default(IEnumerable<T>));
  708. CsvWriter<T>.WriteRow(null, default(T));
  709. }
  710. public static ParseStringDelegate GetParseFn(Type type)
  711. {
  712. var parseFn = JsonTypeSerializer.Instance.GetParseFn(type);
  713. return parseFn;
  714. }
  715. internal static int Register<T, TSerializer>() where TSerializer : ITypeSerializer
  716. {
  717. var i = 0;
  718. if (JsonWriter<T>.WriteFn() != null) i++;
  719. if (JsonWriter.Instance.GetWriteFn<T>() != null) i++;
  720. if (JsonReader.Instance.GetParseFn<T>() != null) i++;
  721. if (JsonReader<T>.Parse(null) != null) i++;
  722. if (JsonReader<T>.GetParseFn() != null) i++;
  723. //if (JsWriter.GetTypeSerializer<JsonTypeSerializer>().GetWriteFn<T>() != null) i++;
  724. if (new List<T>() != null) i++;
  725. if (new T[0] != null) i++;
  726. JsConfig<T>.ExcludeTypeInfo = false;
  727. if (JsConfig<T>.OnDeserializedFn != null) i++;
  728. if (JsConfig<T>.HasDeserializeFn) i++;
  729. if (JsConfig<T>.SerializeFn != null) i++;
  730. if (JsConfig<T>.DeSerializeFn != null) i++;
  731. //JsConfig<T>.SerializeFn = arg => "";
  732. //JsConfig<T>.DeSerializeFn = arg => default(T);
  733. if (TypeConfig<T>.Properties != null) i++;
  734. /*
  735. if (WriteType<T, TSerializer>.Write != null) i++;
  736. if (WriteType<object, TSerializer>.Write != null) i++;
  737. if (DeserializeBuiltin<T>.Parse != null) i++;
  738. if (DeserializeArray<T[], TSerializer>.Parse != null) i++;
  739. DeserializeType<TSerializer>.ExtractType(null);
  740. DeserializeArrayWithElements<T, TSerializer>.ParseGenericArray(null, null);
  741. DeserializeCollection<TSerializer>.ParseCollection<T>(null, null, null);
  742. DeserializeListWithElements<T, TSerializer>.ParseGenericList(null, null, null);
  743. SpecializedQueueElements<T>.ConvertToQueue(null);
  744. SpecializedQueueElements<T>.ConvertToStack(null);
  745. */
  746. WriteListsOfElements<T, TSerializer>.WriteList(null, null);
  747. WriteListsOfElements<T, TSerializer>.WriteIList(null, null);
  748. WriteListsOfElements<T, TSerializer>.WriteEnumerable(null, null);
  749. WriteListsOfElements<T, TSerializer>.WriteListValueType(null, null);
  750. WriteListsOfElements<T, TSerializer>.WriteIListValueType(null, null);
  751. WriteListsOfElements<T, TSerializer>.WriteGenericArrayValueType(null, null);
  752. WriteListsOfElements<T, TSerializer>.WriteArray(null, null);
  753. TranslateListWithElements<T>.LateBoundTranslateToGenericICollection(null, null);
  754. TranslateListWithConvertibleElements<T, T>.LateBoundTranslateToGenericICollection(null, null);
  755. QueryStringWriter<T>.WriteObject(null, null);
  756. return i;
  757. }
  758. internal static void RegisterElement<T, TElement, TSerializer>() where TSerializer : ITypeSerializer
  759. {
  760. DeserializeDictionary<TSerializer>.ParseDictionary<T, TElement>(null, null, null, null);
  761. DeserializeDictionary<TSerializer>.ParseDictionary<TElement, T>(null, null, null, null);
  762. ToStringDictionaryMethods<T, TElement, TSerializer>.WriteIDictionary(null, null, null, null);
  763. ToStringDictionaryMethods<TElement, T, TSerializer>.WriteIDictionary(null, null, null, null);
  764. // Include List deserialisations from the Register<> method above. This solves issue where List<Guid> properties on responses deserialise to null.
  765. // No idea why this is happening because there is no visible exception raised. Suspect MonoTouch is swallowing an AOT exception somewhere.
  766. DeserializeArrayWithElements<TElement, TSerializer>.ParseGenericArray(null, null);
  767. DeserializeListWithElements<TElement, TSerializer>.ParseGenericList(null, null, null);
  768. // Cannot use the line below for some unknown reason - when trying to compile to run on device, mtouch bombs during native code compile.
  769. // Something about this line or its inner workings is offensive to mtouch. Luckily this was not needed for my List<Guide> issue.
  770. // DeserializeCollection<JsonTypeSerializer>.ParseCollection<TElement>(null, null, null);
  771. TranslateListWithElements<TElement>.LateBoundTranslateToGenericICollection(null, typeof(List<TElement>));
  772. TranslateListWithConvertibleElements<TElement, TElement>.LateBoundTranslateToGenericICollection(null, typeof(List<TElement>));
  773. }
  774. }
  775. #endif
  776. internal static HashSet<Type> __uniqueTypes = new HashSet<Type>();
  777. }
  778. #if MONOTOUCH
  779. [MonoTouch.Foundation.Preserve(AllMembers=true)]
  780. internal class Poco
  781. {
  782. public string Dummy { get; set; }
  783. }
  784. #endif
  785. public class JsConfig<T>
  786. {
  787. /// <summary>
  788. /// Always emit type info for this type. Takes precedence over ExcludeTypeInfo
  789. /// </summary>
  790. public static bool IncludeTypeInfo = false;
  791. /// <summary>
  792. /// Never emit type info for this type
  793. /// </summary>
  794. public static bool ExcludeTypeInfo = false;
  795. /// <summary>
  796. /// <see langword="true"/> if the <see cref="ITypeSerializer"/> is configured
  797. /// to take advantage of <see cref="CLSCompliantAttribute"/> specification,
  798. /// to support user-friendly serialized formats, ie emitting camelCasing for JSON
  799. /// and parsing member names and enum values in a case-insensitive manner.
  800. /// </summary>
  801. public static bool EmitCamelCaseNames = false;
  802. public static bool EmitLowercaseUnderscoreNames = false;
  803. /// <summary>
  804. /// Define custom serialization fn for BCL Structs
  805. /// </summary>
  806. private static Func<T, string> serializeFn;
  807. public static Func<T, string> SerializeFn
  808. {
  809. get { return serializeFn; }
  810. set
  811. {
  812. serializeFn = value;
  813. if (value != null)
  814. JsConfig.HasSerializeFn.Add(typeof(T));
  815. else
  816. JsConfig.HasSerializeFn.Remove(typeof(T));
  817. ClearFnCaches();
  818. }
  819. }
  820. /// <summary>
  821. /// Opt-in flag to set some Value Types to be treated as a Ref Type
  822. /// </summary>
  823. public static bool TreatValueAsRefType
  824. {
  825. get { return JsConfig.TreatValueAsRefTypes.Contains(typeof(T)); }
  826. set
  827. {
  828. if (value)
  829. JsConfig.TreatValueAsRefTypes.Add(typeof(T));
  830. else
  831. JsConfig.TreatValueAsRefTypes.Remove(typeof(T));
  832. }
  833. }
  834. /// <summary>
  835. /// Whether there is a fn (raw or otherwise)
  836. /// </summary>
  837. public static bool HasSerializeFn
  838. {
  839. get { return serializeFn != null || rawSerializeFn != null; }
  840. }
  841. /// <summary>
  842. /// Define custom raw serialization fn
  843. /// </summary>
  844. private static Func<T, string> rawSerializeFn;
  845. public static Func<T, string> RawSerializeFn
  846. {
  847. get { return rawSerializeFn; }
  848. set
  849. {
  850. rawSerializeFn = value;
  851. if (value != null)
  852. JsConfig.HasSerializeFn.Add(typeof(T));
  853. else
  854. JsConfig.HasSerializeFn.Remove(typeof(T));
  855. ClearFnCaches();
  856. }
  857. }
  858. /// <summary>
  859. /// Define custom serialization hook
  860. /// </summary>
  861. private static Func<T, T> onSerializingFn;
  862. public static Func<T, T> OnSerializingFn
  863. {
  864. get { return onSerializingFn; }
  865. set { onSerializingFn = value; }
  866. }
  867. /// <summary>
  868. /// Define custom deserialization fn for BCL Structs
  869. /// </summary>
  870. public static Func<string, T> DeSerializeFn;
  871. /// <summary>
  872. /// Define custom raw deserialization fn for objects
  873. /// </summary>
  874. public static Func<string, T> RawDeserializeFn;
  875. public static bool HasDeserializeFn
  876. {
  877. get { return DeSerializeFn != null || RawDeserializeFn != null; }
  878. }
  879. private static Func<T, T> onDeserializedFn;
  880. public static Func<T, T> OnDeserializedFn
  881. {
  882. get { return onDeserializedFn; }
  883. set { onDeserializedFn = value; }
  884. }
  885. /// <summary>
  886. /// Exclude specific properties of this type from being serialized
  887. /// </summary>
  888. public static string[] ExcludePropertyNames;
  889. public static void WriteFn<TSerializer>(TextWriter writer, object obj)
  890. {
  891. if (RawSerializeFn != null)
  892. {
  893. writer.Write(RawSerializeFn((T)obj));
  894. }
  895. else if (SerializeFn != null)
  896. {
  897. var serializer = JsWriter.GetTypeSerializer<TSerializer>();
  898. serializer.WriteString(writer, SerializeFn((T)obj));
  899. }
  900. else
  901. {
  902. var writerFn = JsonWriter.Instance.GetWriteFn<T>();
  903. writerFn(writer, obj);
  904. }
  905. }
  906. public static object ParseFn(string str)
  907. {
  908. return DeSerializeFn(str);
  909. }
  910. internal static object ParseFn(ITypeSerializer serializer, string str)
  911. {
  912. if (RawDeserializeFn != null)
  913. {
  914. return RawDeserializeFn(str);
  915. }
  916. else
  917. {
  918. return DeSerializeFn(serializer.UnescapeString(str));
  919. }
  920. }
  921. internal static void ClearFnCaches()
  922. {
  923. typeof(JsonWriter<>).MakeGenericType(new[] { typeof(T) }).InvokeReset();
  924. typeof(JsvWriter<>).MakeGenericType(new[] { typeof(T) }).InvokeReset();
  925. }
  926. public static void Reset()
  927. {
  928. RawSerializeFn = null;
  929. DeSerializeFn = null;
  930. }
  931. }
  932. public enum JsonPropertyConvention
  933. {
  934. /// <summary>
  935. /// The property names on target types must match property names in the JSON source
  936. /// </summary>
  937. ExactMatch,
  938. /// <summary>
  939. /// The property names on target types may not match the property names in the JSON source
  940. /// </summary>
  941. Lenient
  942. }
  943. public enum JsonDateHandler
  944. {
  945. TimestampOffset,
  946. DCJSCompatible,
  947. ISO8601
  948. }
  949. public enum JsonTimeSpanHandler
  950. {
  951. /// <summary>
  952. /// Uses the xsd format like PT15H10M20S
  953. /// </summary>
  954. DurationFormat,
  955. /// <summary>
  956. /// Uses the standard .net ToString method of the TimeSpan class
  957. /// </summary>
  958. StandardFormat
  959. }
  960. }