PageRenderTime 67ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/LLBL Pro v3.5/AW.DebugVisualizers/EnumerableJSVisualizer.cs

#
C# | 240 lines | 183 code | 18 blank | 39 comment | 53 complexity | bb06610c2754f4351c72ee0f1abc7950 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, BSD-3-Clause, MIT, GPL-2.0, Apache-2.0
  1. //http://msdn.microsoft.com/en-us/library/aa991998(VS.100).aspx 'Use IVisualizerObjectProvider..::.GetData when the object is not serializable by .NET and requires custom serialization.
  2. // In that case, you must also override the VisualizerObjectSource..::.Serialize method.'
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Collections.Specialized;
  7. using System.ComponentModel;
  8. using System.Configuration;
  9. using System.Data;
  10. using System.Diagnostics;
  11. using System.IO;
  12. using System.Linq;
  13. using System.Linq.Dynamic;
  14. using System.Runtime.Serialization;
  15. using System.Xml;
  16. using System.Xml.Schema;
  17. using AW.Helper;
  18. using AW.Winforms.Helpers.DataEditor;
  19. using Microsoft.VisualStudio.DebuggerVisualizers;
  20. using Newtonsoft.Json;
  21. using Newtonsoft.Json.Converters;
  22. using Newtonsoft.Json.Linq;
  23. using Newtonsoft.Json.Serialization;
  24. namespace AW.DebugVisualizers
  25. {
  26. public class EnumerableJSVisualizer : DialogDebuggerVisualizer
  27. {
  28. private IDialogVisualizerService _modalService;
  29. private JToken _firstJToken;
  30. /// <summary>
  31. /// Enumerable Visualizer with JSON Serializer
  32. /// </summary>
  33. public const string Description = "Enumerable Visualizer with JSON Serializer";
  34. /// <summary>
  35. /// Shows the user interface for the visualizer
  36. /// </summary>
  37. /// <param name="windowService">
  38. /// An object of type
  39. /// <see
  40. /// cref="T:Microsoft.VisualStudio.DebuggerVisualizers.IDialogVisualizerService" />
  41. /// , which provides methods your visualizer can use to display Windows forms, controls, and dialogs.
  42. /// </param>
  43. /// <param name="objectProvider">
  44. /// An object of type
  45. /// <see
  46. /// cref="T:Microsoft.VisualStudio.DebuggerVisualizers.IVisualizerObjectProvider" />
  47. /// . This object provides communication from the debugger side of the visualizer to the object source (
  48. /// <see
  49. /// cref="T:Microsoft.VisualStudio.DebuggerVisualizers.VisualizerObjectSource" />
  50. /// ) on the debuggee side.
  51. /// </param>
  52. protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
  53. {
  54. _modalService = windowService;
  55. if (_modalService == null)
  56. throw new NotSupportedException("This debugger does not support modal visualizers");
  57. var s2 = new StreamReader(objectProvider.GetData()).ReadToEnd();
  58. var enumerable = JsonStringToEnumerable(s2);
  59. if (enumerable != null)
  60. _modalService.ShowDialog(FrmDataEditor.CreateDataViewForm(enumerable));
  61. }
  62. private IEnumerable JsonStringToEnumerable(string s2)
  63. {
  64. var deserializeObject = JsonConvert.DeserializeObject(s2, EnumerableJSVisualizerObjectSource.JsonSerializerSettingsTypeNameHandlingAll);
  65. DataTable dataTable = null;
  66. IEnumerable enumerable = null;
  67. if (deserializeObject is JArray)
  68. dataTable = CopyToDataTable(deserializeObject as JArray);
  69. else
  70. {
  71. enumerable = deserializeObject as IEnumerable;
  72. if (enumerable == null)
  73. try
  74. {
  75. dataTable = JsonConvert.DeserializeObject<DataTable>(s2, new DataTableConverter());
  76. }
  77. catch (Exception)
  78. {
  79. var jToken = JToken.Parse(s2);
  80. if (jToken is JArray)
  81. dataTable = CopyToDataTable(jToken as JArray);
  82. else
  83. {
  84. ;
  85. }
  86. }
  87. }
  88. if (dataTable != null)
  89. enumerable = dataTable.DefaultView;
  90. return enumerable;
  91. }
  92. public DataTable CopyToDataTable(JArray source)
  93. {
  94. _firstJToken = source.FirstOrDefault();
  95. if (_firstJToken == null) return new DataTable();
  96. if (!_firstJToken.HasValues)
  97. {
  98. _firstJToken = _firstJToken.Root;
  99. return ValueTypeWrapper.CreateWrapperForBinding(_firstJToken.Root).CopyToDataTable();
  100. }
  101. return new ObjectShredder(GetPropertiesToSerialize).Shred(source, null, null);
  102. }
  103. public IEnumerable<PropertyDescriptor> GetPropertiesToSerialize(Type type)
  104. {
  105. return (from childToken in _firstJToken.OfType<JProperty>()
  106. select
  107. new JPropertyDescriptor(childToken.Name, typeof (object)));
  108. }
  109. public object DeserializeJS(Stream serializationStream)
  110. {
  111. var s = new StreamReader(serializationStream).ReadToEnd();
  112. var enumerable = JsonStringToEnumerable(s);
  113. return enumerable ?? JToken.Parse(s);
  114. }
  115. }
  116. public class EnumerableJSVisualizerObjectSource : VisualizerObjectSource
  117. {
  118. private static readonly ITraceWriter TraceWriter = new MemoryTraceWriter();
  119. public static readonly JsonSerializerSettings JsonSerializerSettingsTypeNameHandlingAll = new JsonSerializerSettings {TraceWriter = TraceWriter, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, TypeNameHandling = TypeNameHandling.All}; //
  120. public static readonly JsonSerializerSettings JsonSerializerSettingsReferenceLoopHandlingIgnore = new JsonSerializerSettings {TraceWriter = TraceWriter, ReferenceLoopHandling = ReferenceLoopHandling.Ignore};
  121. #region Overrides of VisualizerObjectSource
  122. /// <summary>
  123. /// Gets data from the specified object and serializes it into the outgoing data stream
  124. /// This class implements the debugee side of the visualizer. It is responsible for running the commands against the
  125. /// server.
  126. /// </summary>
  127. /// <remarks>
  128. /// Strategy is: if the items are serializable then
  129. /// if the enumerable is also serializable
  130. /// serialize the enumerable
  131. /// else
  132. /// create a ObjectListView to contains the items and serialize that instead.
  133. /// Full back is to copy the enumerable to a data table and serialize that instead.
  134. /// </remarks>
  135. /// <param name="target"> Object being visualized. </param>
  136. /// <param name="outgoingData"> Outgoing data stream. </param>
  137. public override void GetData(object target, Stream outgoingData)
  138. {
  139. var wr = target as WeakReference;
  140. if (wr != null)
  141. target = wr.Target;
  142. var enumerable = target as IEnumerable;
  143. if (enumerable != null)
  144. {
  145. var queryable = enumerable as IQueryable;
  146. if (queryable != null)
  147. enumerable = queryable.Take(100);
  148. SerializeJS(outgoingData, enumerable);
  149. }
  150. else if (target is DataTable)
  151. SerializeJSPlain(outgoingData, target);
  152. }
  153. #endregion
  154. public static void SerializeJS(Stream outgoingData, IEnumerable enumerable)
  155. {
  156. var dataView = enumerable as DataView;
  157. if (dataView != null)
  158. {
  159. SerializeJSTypeNameHandlingAll(outgoingData, dataView.Table);
  160. return;
  161. }
  162. var enumerableType = enumerable.GetType();
  163. // var x = enumerable as IQueryable;
  164. var itemType = MetaDataHelper.GetEnumerableItemType(enumerable);
  165. var fullName = enumerableType.FullName;
  166. if (fullName.Contains("System.Data.Linq"))
  167. SerializeJS(outgoingData, enumerable.CopyToDataTable(), JsonSerializerSettingsReferenceLoopHandlingIgnore);
  168. else if (itemType.Implements(typeof (ISerializable)) || enumerableType.Implements(typeof (ISerializable)) || enumerable is XmlNodeList)
  169. SerializeJS(outgoingData, GeneralHelper.CopyToDataTable(enumerable, MetaDataHelper.GetPropertiesToDisplay), JsonSerializerSettingsReferenceLoopHandlingIgnore);
  170. else if (fullName.Contains("System.Linq.Enumerable"))
  171. SerializeJS(outgoingData, MetaDataHelper.ConvertToList(enumerable), JsonSerializerSettingsReferenceLoopHandlingIgnore);
  172. else if (enumerable is DataRelationCollection || enumerable is SettingsPropertyValueCollection
  173. || enumerableType.Name.Contains("ValuesCollection") || enumerableType.Name.Contains("ValueCollection")
  174. || enumerableType.Name.Contains("NamesCollection") || enumerableType.Name.Contains("NameCollection")
  175. || fullName.Contains("JesseJohnston.ObjectListView") || enumerableType.Name.Contains("KeyCollection") || enumerableType.Name.Contains("KeysCollection")
  176. || itemType.IsAssignableTo(typeof (SettingsProperty))
  177. || itemType.IsAssignableTo(typeof (PropertyDescriptor)) || itemType.IsAssignableTo(typeof (DataRow)) || enumerableType.Implements("SD.LLBLGen.Pro.ORMSupportClasses.IEntityFields"))
  178. SerializeJS(outgoingData, enumerable, JsonSerializerSettingsReferenceLoopHandlingIgnore);
  179. else if (enumerable is XmlSchemaObjectCollection || enumerable is StringDictionary
  180. )
  181. SerializeJS(outgoingData, enumerable, JsonSerializerSettingsReferenceLoopHandlingIgnore);
  182. else
  183. {
  184. if (fullName.Contains("System.Linq.Lookup") || fullName.Contains("System.Xml.Linq.XContainer"))
  185. enumerable = MetaDataHelper.ConvertToArray(enumerable);
  186. SerializeJS(outgoingData, enumerable, itemType.Assembly.GlobalAssemblyCache, enumerableType.Assembly.GlobalAssemblyCache);
  187. }
  188. }
  189. private static void SerializeJS(Stream outgoingData, IEnumerable enumerable, bool itemTypeInGac, bool enumerableTypeInGac)
  190. {
  191. Debug.Write(enumerable.GetType());
  192. if (itemTypeInGac)
  193. if (enumerableTypeInGac)
  194. SerializeJSTypeNameHandlingAll(outgoingData, enumerable);
  195. else
  196. SerializeJS(outgoingData, enumerable, new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Objects, TraceWriter = TraceWriter,});
  197. else if (enumerableTypeInGac)
  198. SerializeJS(outgoingData, enumerable, new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Arrays, TraceWriter = TraceWriter});
  199. else
  200. SerializeJSPlain(outgoingData, enumerable);
  201. }
  202. private static void SerializeJSPlain(Stream outgoingData, object enumerable)
  203. {
  204. StringToStream(outgoingData, JsonConvert.SerializeObject(enumerable));
  205. }
  206. public static void SerializeJSTypeNameHandlingAll(Stream outgoingData, object enumerable)
  207. {
  208. SerializeJS(outgoingData, enumerable, JsonSerializerSettingsTypeNameHandlingAll);
  209. }
  210. private static void SerializeJS(Stream outgoingData, object enumerable, JsonSerializerSettings jsonSerializerSettingsTypeNameHandlingAll)
  211. {
  212. StringToStream(outgoingData, JsonConvert.SerializeObject(enumerable, jsonSerializerSettingsTypeNameHandlingAll));
  213. }
  214. private static void StringToStream(Stream outgoingData, string s1)
  215. {
  216. Debug.Write(TraceWriter);
  217. var writer = new StreamWriter(outgoingData);
  218. writer.Write(s1);
  219. writer.Flush();
  220. }
  221. }
  222. }