PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/applications/Tx/Source/TxLinqPadDriver/TxDataContextDriver.cs

http://rxm4a.codeplex.com
C# | 312 lines | 263 code | 46 blank | 3 comment | 14 complexity | 1b1db1c9f320e2bf0b97eeddd54fb3c3 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0
  1. namespace TxLinqPadDriver
  2. {
  3. using System;
  4. using System.CodeDom.Compiler;
  5. using System.Collections.Generic;
  6. using System.Collections.ObjectModel;
  7. using System.Diagnostics;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Linq.Expressions;
  11. using System.Reflection;
  12. using System.Text;
  13. using System.Threading;
  14. using LINQPad.Extensibility.DataContext;
  15. using Microsoft.CSharp;
  16. using Microsoft.Win32;
  17. using System.Reactive.Subjects;
  18. using System.Reactive.Tx;
  19. using System.Reactive;
  20. using System.Reactive.Linq;
  21. public sealed class TxDataContextDriver : DynamicDataContextDriver
  22. {
  23. const string DataContextTemplate =
  24. @"namespace System.Reactive.Tx
  25. {
  26. using System;
  27. using System.Linq;
  28. using System.Linq.Expressions;
  29. using System.Collections.Generic;
  30. using System.Reactive;
  31. using System.Reactive.Linq;
  32. [usings]
  33. public class StreamScopeWrapper
  34. {
  35. Playback _playback;
  36. public StreamScopeWrapper(Playback playback)
  37. {
  38. _playback = playback;
  39. }
  40. public Playback playback
  41. {
  42. get { return _playback; }
  43. }
  44. [properties]
  45. }
  46. }";
  47. static readonly LocalDataStoreSlot _threadStorageSlot;
  48. static TxDataContextDriver()
  49. {
  50. try
  51. {
  52. ParserRegistry.Init();
  53. TypeCache.Init();
  54. AppDomain.CurrentDomain.AssemblyResolve += TxDataContextDriver.AssemblyResolve;
  55. _threadStorageSlot = Thread.AllocateDataSlot();
  56. }
  57. catch (Exception ex)
  58. {
  59. System.Windows.MessageBox.Show(
  60. "Exception " + ex.Message + "\n\nAt stack Trace: " + ex.StackTrace
  61. , "Error during TraceInsihgt Express initialization");
  62. }
  63. }
  64. public override string Author
  65. {
  66. get { return "Microsoft Corporation"; }
  67. }
  68. public override bool DisallowQueryDisassembly
  69. {
  70. get { return true; }
  71. }
  72. public override string Name
  73. {
  74. get { return "Tx (LINQ to Traces)"; }
  75. }
  76. public override IEnumerable<string> GetAssembliesToAdd()
  77. {
  78. List<Assembly> assemblies = new List<Assembly>(ParserRegistry.GetAssemblies())
  79. {
  80. typeof(ISubject<>).Assembly, // Interfaces
  81. typeof(Observer).Assembly, // Core
  82. typeof(Subject<>).Assembly, // Linq
  83. typeof(Playback).Assembly, // Linq
  84. };
  85. assemblies.AddRange(ParserRegistry.GetAssemblies());
  86. assemblies.AddRange(TypeCache.Assemblies);
  87. return from a in assemblies select a.Location;
  88. }
  89. public override IEnumerable<string> GetNamespacesToAdd()
  90. {
  91. List<string> namespaces = new List<string>()
  92. {
  93. "System",
  94. "System.Linq",
  95. "System.Linq.Expressions",
  96. "System.Reactive",
  97. "System.Reactive.Linq",
  98. };
  99. return namespaces.Concat(ParserRegistry.GetNamespaces());
  100. }
  101. public override string GetConnectionDescription(IConnectionInfo cxInfo)
  102. {
  103. TxProperties properties = new TxProperties(cxInfo);
  104. return properties.ContextName;
  105. }
  106. public override bool ShowConnectionDialog(IConnectionInfo cxInfo, bool isNewConnection)
  107. {
  108. TxProperties properties = new TxProperties(cxInfo);
  109. return new ConnectionDialog(properties).ShowDialog() ?? false;
  110. }
  111. public override ParameterDescriptor[] GetContextConstructorParameters(IConnectionInfo cxInfo)
  112. {
  113. ParameterDescriptor desc = new ParameterDescriptor("playback", typeof(Playback).FullName);
  114. return new ParameterDescriptor[] { desc };
  115. }
  116. public override object[] GetContextConstructorArguments(IConnectionInfo cxInfo)
  117. {
  118. Playback playback = new Playback();
  119. TxProperties properties = new TxProperties(cxInfo);
  120. if (properties.IsRealTime)
  121. {
  122. ParserRegistry.AddSession(playback, properties.SessionName);
  123. }
  124. else
  125. {
  126. ParserRegistry.AddFiles(playback, properties.Files);
  127. }
  128. Thread.SetData(_threadStorageSlot, playback);
  129. return new[] { playback };
  130. }
  131. public override List<ExplorerItem> GetSchemaAndBuildAssembly(IConnectionInfo cxInfo, AssemblyName assemblyToBuild, ref string nameSpace, ref string typeName)
  132. {
  133. nameSpace = "System.Reactive.Tx";
  134. typeName = "StreamScopeWrapper";
  135. List<string> allGeneratedSources = new List<string>();
  136. StringBuilder sbContextUsings = new StringBuilder();
  137. StringBuilder sbContextProperties = new StringBuilder();
  138. TxProperties properties = new TxProperties(cxInfo);
  139. if (properties.IsUsingDirectoryLookup)
  140. {
  141. TypeCache.BuildCache(properties.MetadataDirectory);
  142. }
  143. else
  144. {
  145. TypeCache.BuildCache(properties.MetadataFiles);
  146. }
  147. string dataContext = DataContextTemplate
  148. .Replace("[usings]", sbContextUsings.ToString())
  149. .Replace("[properties]", sbContextProperties.ToString());
  150. allGeneratedSources.Add(dataContext);
  151. CompilerResults results;
  152. string outputName = assemblyToBuild.CodeBase;
  153. using (var codeProvider = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } }))
  154. {
  155. string[] assemblies =
  156. (GetAssembliesToAdd().Concat(new[]
  157. {
  158. typeof(Expression).Assembly.Location,
  159. typeof(Subject<>).Assembly.Location,
  160. typeof(ObservableCollection<>).Assembly.Location,
  161. }).ToArray());
  162. var compilerOptions = new CompilerParameters(assemblies, outputName, true);
  163. results = codeProvider.CompileAssemblyFromSource(compilerOptions, allGeneratedSources.ToArray());
  164. if (results.Errors.Count > 0)
  165. {
  166. StringBuilder sbErr = new StringBuilder();
  167. foreach (object o in results.Errors)
  168. {
  169. sbErr.AppendLine(o.ToString());
  170. }
  171. // Is there any better troubleshooting mechanism?
  172. System.Windows.MessageBox.Show(sbErr.ToString(), "Error compiling generated code");
  173. }
  174. }
  175. Dictionary<Type, long> stat = ParserRegistry.GetTypeStatistics(properties.Files);
  176. return CreateTree(stat);
  177. }
  178. List<ExplorerItem> CreateTree(Dictionary<Type, long> stat)
  179. {
  180. List<ExplorerItem> result = new List<ExplorerItem>();
  181. var x = (from pair in stat
  182. orderby pair.Key.Namespace, pair.Key.Name
  183. select pair).ToArray();
  184. string currentNamespace = null;
  185. ExplorerItem scope = null;
  186. foreach(KeyValuePair<Type, long> pair in x)
  187. {
  188. if (pair.Key.Namespace != currentNamespace)
  189. {
  190. scope = CreateNamespace(pair.Key.Namespace, result);
  191. currentNamespace = pair.Key.Namespace;
  192. };
  193. ExplorerItem eventType = new ExplorerItem(pair.Key.Name, ExplorerItemKind.QueryableObject, ExplorerIcon.Table);
  194. eventType.ToolTipText = "Occurences: " + pair.Value;
  195. eventType.DragText = "playback.GetObservable<" + pair.Key.FullName + ">()";
  196. eventType.Children = new List<ExplorerItem>();
  197. scope.Children.Add(eventType);
  198. foreach (PropertyInfo p in pair.Key.GetProperties())
  199. {
  200. ExplorerItem field = new ExplorerItem(p.Name, ExplorerItemKind.Property, ExplorerIcon.Column);
  201. eventType.Children.Add(field);
  202. field.ToolTipText = p.PropertyType.Name;
  203. }
  204. }
  205. return result;
  206. }
  207. ExplorerItem CreateNamespace(string name, List<ExplorerItem> root)
  208. {
  209. ExplorerItem item = null;
  210. List<ExplorerItem> currentScope = root;
  211. string[] tokens = name.Split('.');
  212. for (int i = 1; i < tokens.Length; i++)
  213. {
  214. string token = tokens[i];
  215. item = currentScope.FirstOrDefault(ei => ei.Text == token);
  216. if (item == null)
  217. {
  218. item = new ExplorerItem(token, ExplorerItemKind.Schema, ExplorerIcon.Schema);
  219. item.Children = new List<ExplorerItem>();
  220. currentScope.Add(item);
  221. }
  222. currentScope = item.Children;
  223. }
  224. return item;
  225. }
  226. public override void PreprocessObjectToWrite(ref object objectToWrite, ObjectGraphInfo info)
  227. {
  228. if (null == objectToWrite)
  229. return;
  230. Type type = objectToWrite.GetType();
  231. if (type.IsGenericType && type.GetInterface(typeof(IObservable<>).Name) != null)
  232. {
  233. Type[] genericArguments = type.GetGenericArguments();
  234. Type eventType = genericArguments[genericArguments.Length - 1];
  235. MethodInfo process = this.GetType().GetMethod("RunSingleOutput", BindingFlags.Static | BindingFlags.Public);
  236. process = process.MakeGenericMethod(eventType);
  237. objectToWrite = process.Invoke(null, new object[] { objectToWrite });
  238. return;
  239. }
  240. }
  241. //// this implements auto-start in "C# Expression" mode
  242. //// In ohter modes Run or Start must be called from the queries
  243. public static IEnumerable<T> RunSingleOutput<T>(IObservable<T> output)
  244. {
  245. var playback = (Playback)Thread.GetData(_threadStorageSlot);
  246. var list = playback.BufferOutput(output);
  247. playback.Run();
  248. return list;
  249. }
  250. static Assembly AssemblyResolve(object sender, ResolveEventArgs args)
  251. {
  252. string assemblyname = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll";
  253. string root = System.IO.Path.Combine(System.IO.Path.GetTempPath(), @"LINQPad\");
  254. var assemblies = Directory.EnumerateFiles(root, assemblyname, SearchOption.AllDirectories);
  255. foreach (string path in assemblies)
  256. {
  257. return Assembly.LoadFrom(path);
  258. }
  259. return null;
  260. }
  261. }
  262. }