PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/SDK/api/CSharp/fastJSON/JSON.cs

https://bitbucket.org/ehvattum/draugr_contrib
C# | 859 lines | 696 code | 120 blank | 43 comment | 234 complexity | f171c94d917018ecc23434131e88ca07 MD5 | raw file
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. #if !SILVERLIGHT
  5. using System.Data;
  6. #endif
  7. using System.Globalization;
  8. using System.IO;
  9. using System.Reflection;
  10. using System.Reflection.Emit;
  11. namespace fastJSON
  12. {
  13. public delegate string Serialize(object data);
  14. public delegate object Deserialize(string data);
  15. public sealed class JSONParameters
  16. {
  17. /// <summary>
  18. /// Use the optimized fast Dataset Schema format (default = True)
  19. /// </summary>
  20. public bool UseOptimizedDatasetSchema = true;
  21. /// <summary>
  22. /// Use the fast GUID format (default = True)
  23. /// </summary>
  24. public bool UseFastGuid = true;
  25. /// <summary>
  26. /// Serialize null values to the output (default = True)
  27. /// </summary>
  28. public bool SerializeNullValues = true;
  29. /// <summary>
  30. /// Use the UTC date format (default = True)
  31. /// </summary>
  32. public bool UseUTCDateTime = true;
  33. /// <summary>
  34. /// Show the readonly properties of types in the output (default = False)
  35. /// </summary>
  36. public bool ShowReadOnlyProperties = false;
  37. /// <summary>
  38. /// Use the $types extension to optimise the output json (default = True)
  39. /// </summary>
  40. public bool UsingGlobalTypes = true;
  41. /// <summary>
  42. /// ** work in progress
  43. /// </summary>
  44. public bool IgnoreCaseOnDeserialize = false;
  45. /// <summary>
  46. /// Anonymous types have read only properties
  47. /// </summary>
  48. public bool EnableAnonymousTypes = false;
  49. /// <summary>
  50. /// Enable fastJSON extensions $types, $type, $map (default = True)
  51. /// </summary>
  52. public bool UseExtensions = true;
  53. /// <summary>
  54. /// Use escaped unicode i.e. \uXXXX format for non ASCII characters (default = True)
  55. /// </summary>
  56. public bool UseEscapedUnicode = true;
  57. public void FixValues()
  58. {
  59. if (UseExtensions == false) // disable conflicting params
  60. {
  61. UsingGlobalTypes = false;
  62. }
  63. }
  64. }
  65. public sealed class JSON
  66. {
  67. //public readonly static JSON Instance = new JSON();
  68. [ThreadStatic]
  69. private static JSON _instance;
  70. public static JSON Instance
  71. {
  72. get { return _instance ?? (_instance = new JSON()); }
  73. }
  74. private JSON()
  75. {
  76. }
  77. /// <summary>
  78. /// You can set these paramters globally for all calls
  79. /// </summary>
  80. public JSONParameters Parameters = new JSONParameters();
  81. private JSONParameters _params;
  82. public string ToJSON(object obj)
  83. {
  84. _params = Parameters;
  85. _params.FixValues();
  86. Reflection.Instance.ShowReadOnlyProperties = _params.ShowReadOnlyProperties;
  87. return ToJSON(obj, Parameters);
  88. }
  89. public string ToJSON(object obj, JSONParameters param)
  90. {
  91. _params = param;
  92. _params.FixValues();
  93. Reflection.Instance.ShowReadOnlyProperties = _params.ShowReadOnlyProperties;
  94. Type t = null;
  95. if (obj == null)
  96. return "null";
  97. if (obj.GetType().IsGenericType)
  98. t = obj.GetType().GetGenericTypeDefinition();
  99. if (t == typeof(Dictionary<,>) || t == typeof(List<>))
  100. _params.UsingGlobalTypes = false;
  101. // FEATURE : enable extensions when you can deserialize anon types
  102. if (_params.EnableAnonymousTypes) { _params.UseExtensions = false; _params.UsingGlobalTypes = false; Reflection.Instance.ShowReadOnlyProperties = true; }
  103. _usingglobals = _params.UsingGlobalTypes;
  104. return new JSONSerializer(_params).ConvertToJSON(obj);
  105. }
  106. public object Parse(string json)
  107. {
  108. _params = Parameters;
  109. Reflection.Instance.ShowReadOnlyProperties = _params.ShowReadOnlyProperties;
  110. return new JsonParser(json, _params.IgnoreCaseOnDeserialize).Decode();
  111. }
  112. public T ToObject<T>(string json)
  113. {
  114. return (T)ToObject(json, typeof(T));
  115. }
  116. public object ToObject(string json)
  117. {
  118. return ToObject(json, null);
  119. }
  120. public object ToObject(string json, Type type)
  121. {
  122. _params = Parameters;
  123. _params.FixValues();
  124. Reflection.Instance.ShowReadOnlyProperties = _params.ShowReadOnlyProperties;
  125. Type t = null;
  126. if (type != null && type.IsGenericType)
  127. t = type.GetGenericTypeDefinition();
  128. if (t == typeof(Dictionary<,>) || t == typeof(List<>))
  129. _params.UsingGlobalTypes = false;
  130. _usingglobals = _params.UsingGlobalTypes;
  131. object o = new JsonParser(json, Parameters.IgnoreCaseOnDeserialize).Decode();
  132. if (o == null)
  133. return null;
  134. #if !SILVERLIGHT
  135. if (type != null && type == typeof(DataSet))
  136. return CreateDataset(o as Dictionary<string, object>, null);
  137. if (type != null && type == typeof(DataTable))
  138. return CreateDataTable(o as Dictionary<string, object>, null);
  139. #endif
  140. if (o is IDictionary)
  141. {
  142. if (type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) // deserialize a dictionary
  143. return RootDictionary(o, type);
  144. else // deserialize an object
  145. return ParseDictionary(o as Dictionary<string, object>, null, type, null);
  146. }
  147. if (o is List<object>)
  148. {
  149. if (type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) // kv format
  150. return RootDictionary(o, type);
  151. if (type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) // deserialize to generic list
  152. return RootList(o, type);
  153. else
  154. return (o as List<object>).ToArray();
  155. }
  156. if (type!=null && o.GetType() != type)
  157. return ChangeType(o, type);
  158. return o;
  159. }
  160. public string Beautify(string input)
  161. {
  162. return Formatter.PrettyPrint(input);
  163. }
  164. public object FillObject(object input, string json)
  165. {
  166. _params = Parameters;
  167. _params.FixValues();
  168. Reflection.Instance.ShowReadOnlyProperties = _params.ShowReadOnlyProperties;
  169. Dictionary<string, object> ht = new JsonParser(json, Parameters.IgnoreCaseOnDeserialize).Decode() as Dictionary<string, object>;
  170. if (ht == null) return null;
  171. return ParseDictionary(ht, null, input.GetType(), input);
  172. }
  173. public object DeepCopy(object obj)
  174. {
  175. return ToObject(ToJSON(obj));
  176. }
  177. public T DeepCopy<T>(T obj)
  178. {
  179. return ToObject<T>(ToJSON(obj));
  180. }
  181. #if CUSTOMTYPE
  182. internal SafeDictionary<Type, Serialize> _customSerializer = new SafeDictionary<Type, Serialize>();
  183. internal SafeDictionary<Type, Deserialize> _customDeserializer = new SafeDictionary<Type, Deserialize>();
  184. public void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer)
  185. {
  186. if (type != null && serializer != null && deserializer != null)
  187. {
  188. _customSerializer.Add(type, serializer);
  189. _customDeserializer.Add(type, deserializer);
  190. // reset property cache
  191. _propertycache = new SafeDictionary<string, SafeDictionary<string, myPropInfo>>();
  192. }
  193. }
  194. internal bool IsTypeRegistered(Type t)
  195. {
  196. Serialize s;
  197. return _customSerializer.TryGetValue(t, out s);
  198. }
  199. #endif
  200. #region [ JSON specific reflection ]
  201. private struct myPropInfo
  202. {
  203. public bool filled;
  204. public Type pt;
  205. public Type bt;
  206. public Type changeType;
  207. public bool isDictionary;
  208. public bool isValueType;
  209. public bool isGenericType;
  210. public bool isArray;
  211. public bool isByteArray;
  212. public bool isGuid;
  213. #if !SILVERLIGHT
  214. public bool isDataSet;
  215. public bool isDataTable;
  216. public bool isHashtable;
  217. #endif
  218. public Reflection.GenericSetter setter;
  219. public bool isEnum;
  220. public bool isDateTime;
  221. public Type[] GenericTypes;
  222. public bool isInt;
  223. public bool isLong;
  224. public bool isString;
  225. public bool isBool;
  226. public bool isClass;
  227. public Reflection.GenericGetter getter;
  228. public bool isStringDictionary;
  229. public string Name;
  230. #if CUSTOMTYPE
  231. public bool isCustomType;
  232. #endif
  233. public bool CanWrite;
  234. }
  235. SafeDictionary<string, SafeDictionary<string, myPropInfo>> _propertycache = new SafeDictionary<string, SafeDictionary<string, myPropInfo>>();
  236. private SafeDictionary<string, myPropInfo> Getproperties(Type type, string typename)
  237. {
  238. SafeDictionary<string, myPropInfo> sd = null;
  239. if (_propertycache.TryGetValue(typename, out sd))
  240. {
  241. return sd;
  242. }
  243. else
  244. {
  245. sd = new SafeDictionary<string, myPropInfo>();
  246. PropertyInfo[] pr = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
  247. foreach (PropertyInfo p in pr)
  248. {
  249. myPropInfo d = CreateMyProp(p.PropertyType, p.Name);
  250. d.CanWrite = p.CanWrite;
  251. d.setter = Reflection.CreateSetMethod(type, p);
  252. d.getter = Reflection.CreateGetMethod(type, p);
  253. sd.Add(p.Name, d);
  254. }
  255. FieldInfo[] fi = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
  256. foreach (FieldInfo f in fi)
  257. {
  258. myPropInfo d = CreateMyProp(f.FieldType, f.Name);
  259. d.setter = Reflection.CreateSetField(type, f);
  260. d.getter = Reflection.CreateGetField(type, f);
  261. sd.Add(f.Name, d);
  262. }
  263. _propertycache.Add(typename, sd);
  264. return sd;
  265. }
  266. }
  267. private myPropInfo CreateMyProp(Type t, string name)
  268. {
  269. myPropInfo d = new myPropInfo();
  270. d.filled = true;
  271. d.CanWrite = true;
  272. d.pt = t;
  273. d.Name = name;
  274. d.isDictionary = t.Name.Contains("Dictionary");
  275. if (d.isDictionary)
  276. d.GenericTypes = t.GetGenericArguments();
  277. d.isValueType = t.IsValueType;
  278. d.isGenericType = t.IsGenericType;
  279. d.isArray = t.IsArray;
  280. if (d.isArray)
  281. d.bt = t.GetElementType();
  282. if (d.isGenericType)
  283. d.bt = t.GetGenericArguments()[0];
  284. d.isByteArray = t == typeof(byte[]);
  285. d.isGuid = (t == typeof(Guid) || t == typeof(Guid?));
  286. #if !SILVERLIGHT
  287. d.isHashtable = t == typeof(Hashtable);
  288. d.isDataSet = t == typeof(DataSet);
  289. d.isDataTable = t == typeof(DataTable);
  290. #endif
  291. d.changeType = GetChangeType(t);
  292. d.isEnum = t.IsEnum;
  293. d.isDateTime = t == typeof(DateTime) || t == typeof(DateTime?);
  294. d.isInt = t == typeof(int) || t == typeof(int?);
  295. d.isLong = t == typeof(long) || t == typeof(long?);
  296. d.isString = t == typeof(string);
  297. d.isBool = t == typeof(bool) || t == typeof(bool?);
  298. d.isClass = t.IsClass;
  299. if (d.isDictionary && d.GenericTypes.Length > 0 && d.GenericTypes[0] == typeof(string))
  300. d.isStringDictionary = true;
  301. #if CUSTOMTYPE
  302. if (IsTypeRegistered(t))
  303. d.isCustomType = true;
  304. #endif
  305. return d;
  306. }
  307. private object ChangeType(object value, Type conversionType)
  308. {
  309. if (conversionType == typeof(int))
  310. return (int)((long)value);
  311. else if (conversionType == typeof(long))
  312. return (long)value;
  313. else if (conversionType == typeof(string))
  314. return (string)value;
  315. else if (conversionType == typeof(Guid))
  316. return CreateGuid((string)value);
  317. else if (conversionType.IsEnum)
  318. return CreateEnum(conversionType, (string)value);
  319. #if CUSTOMTYPE
  320. else if (IsTypeRegistered(conversionType))
  321. return CreateCustom((string)value, conversionType);
  322. #endif
  323. return Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture);
  324. }
  325. #endregion
  326. #region [ p r i v a t e m e t h o d s ]
  327. private object RootList(object parse, Type type)
  328. {
  329. Type[] gtypes = type.GetGenericArguments();
  330. IList o = (IList)Reflection.Instance.FastCreateInstance(type);
  331. foreach (var k in (IList)parse)
  332. {
  333. _usingglobals = false;
  334. object v = k;
  335. if (k is Dictionary<string, object>)
  336. v = ParseDictionary(k as Dictionary<string, object>, null, gtypes[0], null);
  337. else
  338. v = ChangeType(k, gtypes[0]);
  339. o.Add(v);
  340. }
  341. return o;
  342. }
  343. private object RootDictionary(object parse, Type type)
  344. {
  345. Type[] gtypes = type.GetGenericArguments();
  346. if (parse is Dictionary<string, object>)
  347. {
  348. IDictionary o = (IDictionary)Reflection.Instance.FastCreateInstance(type);
  349. foreach (var kv in (Dictionary<string, object>)parse)
  350. {
  351. object v;
  352. object k = ChangeType(kv.Key, gtypes[0]);
  353. if (kv.Value is Dictionary<string, object>)
  354. v = ParseDictionary(kv.Value as Dictionary<string, object>, null, gtypes[1], null);
  355. else if (kv.Value is List<object>)
  356. v = CreateArray(kv.Value as List<object>, typeof(object), typeof(object), null);
  357. else
  358. v = ChangeType(kv.Value, gtypes[1]);
  359. o.Add(k, v);
  360. }
  361. return o;
  362. }
  363. if (parse is List<object>)
  364. return CreateDictionary(parse as List<object>, type, gtypes, null);
  365. return null;
  366. }
  367. bool _usingglobals = false;
  368. private object ParseDictionary(Dictionary<string, object> d, Dictionary<string, object> globaltypes, Type type, object input)
  369. {
  370. object tn = "";
  371. if (d.TryGetValue("$types", out tn))
  372. {
  373. _usingglobals = true;
  374. globaltypes = new Dictionary<string, object>();
  375. foreach (var kv in (Dictionary<string, object>)tn)
  376. {
  377. globaltypes.Add((string)kv.Value, kv.Key);
  378. }
  379. }
  380. bool found = d.TryGetValue("$type", out tn);
  381. #if !SILVERLIGHT
  382. if (found == false && type == typeof(System.Object))
  383. {
  384. return CreateDataset(d, globaltypes);
  385. }
  386. #endif
  387. if (found)
  388. {
  389. if (_usingglobals)
  390. {
  391. object tname = "";
  392. if (globaltypes.TryGetValue((string)tn, out tname))
  393. tn = tname;
  394. }
  395. type = Reflection.Instance.GetTypeFromCache((string)tn);
  396. }
  397. if (type == null)
  398. throw new Exception("Cannot determine type");
  399. string typename = type.FullName;
  400. object o = input;
  401. if (o == null)
  402. o = Reflection.Instance.FastCreateInstance(type);
  403. SafeDictionary<string, myPropInfo> props = Getproperties(type, typename);
  404. foreach (string n in d.Keys)
  405. {
  406. string name = n;
  407. if (_params.IgnoreCaseOnDeserialize) name = name.ToLower();
  408. if (name == "$map")
  409. {
  410. ProcessMap(o, props, (Dictionary<string, object>)d[name]);
  411. continue;
  412. }
  413. myPropInfo pi;
  414. if (props.TryGetValue(name, out pi) == false)
  415. continue;
  416. if (pi.filled && pi.CanWrite)
  417. {
  418. object v = d[name];
  419. if (v != null)
  420. {
  421. object oset = null;
  422. if (pi.isInt)
  423. oset = (int)((long)v);
  424. #if CUSTOMTYPE
  425. else if (pi.isCustomType)
  426. oset = CreateCustom((string)v, pi.pt);
  427. #endif
  428. else if (pi.isLong)
  429. oset = (long)v;
  430. else if (pi.isString)
  431. oset = (string)v;
  432. else if (pi.isBool)
  433. oset = (bool)v;
  434. else if (pi.isGenericType && pi.isValueType == false && pi.isDictionary == false && v is List<object>)
  435. oset = CreateGenericList((List<object>)v, pi.pt, pi.bt, globaltypes);
  436. else if (pi.isByteArray)
  437. oset = Convert.FromBase64String((string)v);
  438. else if (pi.isArray && pi.isValueType == false)
  439. oset = CreateArray((List<object>)v, pi.pt, pi.bt, globaltypes);
  440. else if (pi.isGuid)
  441. oset = CreateGuid((string)v);
  442. #if !SILVERLIGHT
  443. else if (pi.isDataSet)
  444. oset = CreateDataset((Dictionary<string, object>)v, globaltypes);
  445. else if (pi.isDataTable)
  446. oset = this.CreateDataTable((Dictionary<string, object>)v, globaltypes);
  447. #endif
  448. else if (pi.isStringDictionary)
  449. oset = CreateStringKeyDictionary((Dictionary<string, object>)v, pi.pt, pi.GenericTypes, globaltypes);
  450. #if !SILVERLIGHT
  451. else if (pi.isDictionary || pi.isHashtable)
  452. #else
  453. else if (pi.isDictionary)
  454. #endif
  455. oset = CreateDictionary((List<object>)v, pi.pt, pi.GenericTypes, globaltypes);
  456. else if (pi.isEnum)
  457. oset = CreateEnum(pi.pt, (string)v);
  458. else if (pi.isDateTime)
  459. oset = CreateDateTime((string)v);
  460. else if (pi.isClass && v is Dictionary<string, object>)
  461. oset = ParseDictionary((Dictionary<string, object>)v, globaltypes, pi.pt, pi.getter(o));
  462. else if (pi.isValueType)
  463. oset = ChangeType(v, pi.changeType);
  464. else if (v is List<object>)
  465. oset = CreateArray((List<object>)v, pi.pt, typeof(object), globaltypes);
  466. else
  467. oset = v;
  468. o = pi.setter(o, oset);
  469. }
  470. }
  471. }
  472. return o;
  473. }
  474. #if CUSTOMTYPE
  475. private object CreateCustom(string v, Type type)
  476. {
  477. Deserialize d;
  478. _customDeserializer.TryGetValue(type, out d);
  479. return d(v);
  480. }
  481. #endif
  482. private void ProcessMap(object obj, SafeDictionary<string, JSON.myPropInfo> props, Dictionary<string, object> dic)
  483. {
  484. foreach (KeyValuePair<string, object> kv in dic)
  485. {
  486. myPropInfo p = props[kv.Key];
  487. object o = p.getter(obj);
  488. Type t = Type.GetType((string)kv.Value);
  489. if (t == typeof(Guid))
  490. p.setter(obj, CreateGuid((string)o));
  491. }
  492. }
  493. private long CreateLong(string s)
  494. {
  495. long num = 0;
  496. bool neg = false;
  497. foreach (char cc in s)
  498. {
  499. if (cc == '-')
  500. neg = true;
  501. else if (cc == '+')
  502. neg = false;
  503. else
  504. {
  505. num *= 10;
  506. num += (int)(cc - '0');
  507. }
  508. }
  509. return neg ? -num : num;
  510. }
  511. private object CreateEnum(Type pt, string v)
  512. {
  513. // TODO : optimize create enum
  514. #if !SILVERLIGHT
  515. return Enum.Parse(pt, v);
  516. #else
  517. return Enum.Parse(pt, v, true);
  518. #endif
  519. }
  520. private Guid CreateGuid(string s)
  521. {
  522. if (s.Length > 30)
  523. return new Guid(s);
  524. else
  525. return new Guid(Convert.FromBase64String(s));
  526. }
  527. private DateTime CreateDateTime(string value)
  528. {
  529. bool utc = false;
  530. // 0123456789012345678
  531. // datetime format = yyyy-MM-dd HH:mm:ss
  532. int year = (int)CreateLong(value.Substring(0, 4));
  533. int month = (int)CreateLong(value.Substring(5, 2));
  534. int day = (int)CreateLong(value.Substring(8, 2));
  535. int hour = (int)CreateLong(value.Substring(11, 2));
  536. int min = (int)CreateLong(value.Substring(14, 2));
  537. int sec = (int)CreateLong(value.Substring(17, 2));
  538. if (value.EndsWith("Z"))
  539. utc = true;
  540. if (_params.UseUTCDateTime == false && utc == false)
  541. return new DateTime(year, month, day, hour, min, sec);
  542. else
  543. return new DateTime(year, month, day, hour, min, sec, DateTimeKind.Utc).ToLocalTime();
  544. }
  545. private object CreateArray(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes)
  546. {
  547. Array col = Array.CreateInstance(bt, data.Count);
  548. // create an array of objects
  549. for (int i = 0; i < data.Count; i++)// each (object ob in data)
  550. {
  551. object ob = data[i];
  552. if (ob is IDictionary)
  553. col.SetValue(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt, null), i);
  554. else
  555. col.SetValue(ChangeType(ob, bt), i);
  556. }
  557. return col;
  558. }
  559. private object CreateGenericList(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes)
  560. {
  561. IList col = (IList)Reflection.Instance.FastCreateInstance(pt);
  562. // create an array of objects
  563. foreach (object ob in data)
  564. {
  565. if (ob is IDictionary)
  566. col.Add(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt, null));
  567. else if (ob is List<object>)
  568. col.Add(((List<object>)ob).ToArray());
  569. else
  570. col.Add(ChangeType(ob, bt));
  571. }
  572. return col;
  573. }
  574. private object CreateStringKeyDictionary(Dictionary<string, object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes)
  575. {
  576. var col = (IDictionary)Reflection.Instance.FastCreateInstance(pt);
  577. Type t1 = null;
  578. Type t2 = null;
  579. if (types != null)
  580. {
  581. t1 = types[0];
  582. t2 = types[1];
  583. }
  584. foreach (KeyValuePair<string, object> values in reader)
  585. {
  586. var key = values.Key;//ChangeType(values.Key, t1);
  587. object val = null;
  588. if (values.Value is Dictionary<string, object>)
  589. val = ParseDictionary((Dictionary<string, object>)values.Value, globalTypes, t2, null);
  590. else
  591. val = ChangeType(values.Value, t2);
  592. col.Add(key, val);
  593. }
  594. return col;
  595. }
  596. private object CreateDictionary(List<object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes)
  597. {
  598. IDictionary col = (IDictionary)Reflection.Instance.FastCreateInstance(pt);
  599. Type t1 = null;
  600. Type t2 = null;
  601. if (types != null)
  602. {
  603. t1 = types[0];
  604. t2 = types[1];
  605. }
  606. foreach (Dictionary<string, object> values in reader)
  607. {
  608. object key = values["k"];
  609. object val = values["v"];
  610. if (key is Dictionary<string, object>)
  611. key = ParseDictionary((Dictionary<string, object>)key, globalTypes, t1, null);
  612. else
  613. key = ChangeType(key, t1);
  614. if (val is Dictionary<string, object>)
  615. val = ParseDictionary((Dictionary<string, object>)val, globalTypes, t2, null);
  616. else
  617. val = ChangeType(val, t2);
  618. col.Add(key, val);
  619. }
  620. return col;
  621. }
  622. private Type GetChangeType(Type conversionType)
  623. {
  624. if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
  625. return conversionType.GetGenericArguments()[0];
  626. return conversionType;
  627. }
  628. #if !SILVERLIGHT
  629. private DataSet CreateDataset(Dictionary<string, object> reader, Dictionary<string, object> globalTypes)
  630. {
  631. DataSet ds = new DataSet();
  632. ds.EnforceConstraints = false;
  633. ds.BeginInit();
  634. // read dataset schema here
  635. ReadSchema(reader, ds, globalTypes);
  636. foreach (KeyValuePair<string, object> pair in reader)
  637. {
  638. if (pair.Key == "$type" || pair.Key == "$schema") continue;
  639. List<object> rows = (List<object>)pair.Value;
  640. if (rows == null) continue;
  641. DataTable dt = ds.Tables[pair.Key];
  642. ReadDataTable(rows, dt);
  643. }
  644. ds.EndInit();
  645. return ds;
  646. }
  647. private void ReadSchema(Dictionary<string, object> reader, DataSet ds, Dictionary<string, object> globalTypes)
  648. {
  649. var schema = reader["$schema"];
  650. if (schema is string)
  651. {
  652. TextReader tr = new StringReader((string)schema);
  653. ds.ReadXmlSchema(tr);
  654. }
  655. else
  656. {
  657. DatasetSchema ms = (DatasetSchema)ParseDictionary((Dictionary<string, object>)schema, globalTypes, typeof(DatasetSchema), null);
  658. ds.DataSetName = ms.Name;
  659. for (int i = 0; i < ms.Info.Count; i += 3)
  660. {
  661. if (ds.Tables.Contains(ms.Info[i]) == false)
  662. ds.Tables.Add(ms.Info[i]);
  663. ds.Tables[ms.Info[i]].Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2]));
  664. }
  665. }
  666. }
  667. private void ReadDataTable(List<object> rows, DataTable dt)
  668. {
  669. dt.BeginInit();
  670. dt.BeginLoadData();
  671. List<int> guidcols = new List<int>();
  672. List<int> datecol = new List<int>();
  673. foreach (DataColumn c in dt.Columns)
  674. {
  675. if (c.DataType == typeof(Guid) || c.DataType == typeof(Guid?))
  676. guidcols.Add(c.Ordinal);
  677. if (_params.UseUTCDateTime && (c.DataType == typeof(DateTime) || c.DataType == typeof(DateTime?)))
  678. datecol.Add(c.Ordinal);
  679. }
  680. foreach (List<object> row in rows)
  681. {
  682. object[] v = new object[row.Count];
  683. row.CopyTo(v, 0);
  684. foreach (int i in guidcols)
  685. {
  686. string s = (string)v[i];
  687. if (s != null && s.Length < 36)
  688. v[i] = new Guid(Convert.FromBase64String(s));
  689. }
  690. if (_params.UseUTCDateTime)
  691. {
  692. foreach (int i in datecol)
  693. {
  694. string s = (string)v[i];
  695. if (s != null)
  696. v[i] = CreateDateTime(s);
  697. }
  698. }
  699. dt.Rows.Add(v);
  700. }
  701. dt.EndLoadData();
  702. dt.EndInit();
  703. }
  704. DataTable CreateDataTable(Dictionary<string, object> reader, Dictionary<string, object> globalTypes)
  705. {
  706. var dt = new DataTable();
  707. // read dataset schema here
  708. var schema = reader["$schema"];
  709. if (schema is string)
  710. {
  711. TextReader tr = new StringReader((string)schema);
  712. dt.ReadXmlSchema(tr);
  713. }
  714. else
  715. {
  716. var ms = (DatasetSchema)this.ParseDictionary((Dictionary<string, object>)schema, globalTypes, typeof(DatasetSchema), null);
  717. dt.TableName = ms.Info[0];
  718. for (int i = 0; i < ms.Info.Count; i += 3)
  719. {
  720. dt.Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2]));
  721. }
  722. }
  723. foreach (var pair in reader)
  724. {
  725. if (pair.Key == "$type" || pair.Key == "$schema")
  726. continue;
  727. var rows = (List<object>)pair.Value;
  728. if (rows == null)
  729. continue;
  730. if (!dt.TableName.Equals(pair.Key, StringComparison.InvariantCultureIgnoreCase))
  731. continue;
  732. ReadDataTable(rows, dt);
  733. }
  734. return dt;
  735. }
  736. #endif
  737. #endregion
  738. }
  739. }