From b2907ff29c02b8d73f3dc0c89de2cc008ef29533 Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Mon, 15 Sep 2014 02:12:46 +0200 Subject: [PATCH 1/4] Initial step for explicit capture --- RxSpy/Proxy/QueryServiceProxy.cs | 4 +++- RxSpy/RxSpySession.cs | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/RxSpy/Proxy/QueryServiceProxy.cs b/RxSpy/Proxy/QueryServiceProxy.cs index e04f031..830c67a 100644 --- a/RxSpy/Proxy/QueryServiceProxy.cs +++ b/RxSpy/Proxy/QueryServiceProxy.cs @@ -28,14 +28,16 @@ internal class QueryLanguageProxy : RealProxy, IRemotingTypeInfo readonly Type _queryLanguageType; readonly Type _queryLanguageInterface; readonly RxSpySession _session; + readonly bool _explicitCapture; - internal QueryLanguageProxy(RxSpySession session, object realQueryLanguage) + internal QueryLanguageProxy(RxSpySession session, object realQueryLanguage, bool explicitCapture) : base(typeof(ContextBoundObject)) { _queryLanguage = realQueryLanguage; _queryLanguageType = realQueryLanguage.GetType(); _queryLanguageInterface = _queryLanguageType.GetInterface("IQueryLanguage"); _session = session; + _explicitCapture = explicitCapture; } public override IMessage Invoke(IMessage msg) diff --git a/RxSpy/RxSpySession.cs b/RxSpy/RxSpySession.cs index e2a5b3e..c07e7a9 100644 --- a/RxSpy/RxSpySession.cs +++ b/RxSpy/RxSpySession.cs @@ -26,12 +26,12 @@ public class RxSpySession: IRxSpyEventHandler, IDisposable _eventHandler = eventHandler; } - public static RxSpySession Launch(string pathToRxSpy = null) + public static RxSpySession Launch(string pathToRxSpy = null, bool explicitCapture = false) { - return Launch(TimeSpan.FromSeconds(10), pathToRxSpy); + return Launch(TimeSpan.FromSeconds(10), pathToRxSpy, explicitCapture); } - public static RxSpySession Launch(TimeSpan timeout, string pathToRxSpy = null) + public static RxSpySession Launch(TimeSpan timeout, string pathToRxSpy = null, bool explicitCapture = false) { if (_launched == 1) throw new InvalidOperationException("Session already created"); @@ -54,7 +54,7 @@ public static RxSpySession Launch(TimeSpan timeout, string pathToRxSpy = null) return Launch(server); } - public static RxSpySession Launch(IRxSpyEventHandler eventHandler) + public static RxSpySession Launch(IRxSpyEventHandler eventHandler, bool explicitCapture = false) { var session = new RxSpySession(eventHandler); Current = session; @@ -62,7 +62,7 @@ public static RxSpySession Launch(IRxSpyEventHandler eventHandler) if (Interlocked.CompareExchange(ref _launched, 1, 0) != 0) throw new InvalidOperationException("Session already created"); - InstallInterceptingQueryLanguage(session); + InstallInterceptingQueryLanguage(session, explicitCapture); return session; } @@ -110,7 +110,7 @@ static string FindGuiPath(string explicitPathToRxSpy) throw new ArgumentException("Can't find RxSpy.LiveView.exe - either copy it and its DLLs to your output directory or pass in a path to Create"); } - static void InstallInterceptingQueryLanguage(RxSpySession session) + static void InstallInterceptingQueryLanguage(RxSpySession session, bool explictCapture) { // TODO: Verify that the version is supported var rxLinqAssembly = Assembly.Load(new AssemblyName("System.Reactive.Linq")); @@ -123,7 +123,7 @@ static void InstallInterceptingQueryLanguage(RxSpySession session) var actualImplementation = defaultImplementationField.GetValue(null); - object proxy = new QueryLanguageProxy(session, actualImplementation) + object proxy = new QueryLanguageProxy(session, actualImplementation, explictCapture) .GetTransparentProxy(); defaultImplementationField.SetValue(null, proxy); From 0e29164f97b16149a92d174799460dbaca1bb048 Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Mon, 15 Sep 2014 02:13:38 +0200 Subject: [PATCH 2/4] Remove RxSpyGroup for now It's untested and easily confused with explicit capture --- RxSpy/Proxy/QueryServiceProxy.cs | 5 ----- RxSpy/RxSpy.csproj | 1 - RxSpy/Utils/RxSpyGroup.cs | 31 ------------------------------- 3 files changed, 37 deletions(-) delete mode 100644 RxSpy/Utils/RxSpyGroup.cs diff --git a/RxSpy/Proxy/QueryServiceProxy.cs b/RxSpy/Proxy/QueryServiceProxy.cs index 830c67a..6e90c5d 100644 --- a/RxSpy/Proxy/QueryServiceProxy.cs +++ b/RxSpy/Proxy/QueryServiceProxy.cs @@ -47,11 +47,6 @@ public override IMessage Invoke(IMessage msg) if (call == null) throw new ArgumentException("QueryLanguageProxy only supports call messages"); - if (RxSpyGroup.IsActive) - { - return ForwardCall(call); - } - var method = (System.Reflection.MethodInfo)call.MethodBase; int skipFrames; diff --git a/RxSpy/RxSpy.csproj b/RxSpy/RxSpy.csproj index ef4e209..8d6114b 100644 --- a/RxSpy/RxSpy.csproj +++ b/RxSpy/RxSpy.csproj @@ -92,7 +92,6 @@ - diff --git a/RxSpy/Utils/RxSpyGroup.cs b/RxSpy/Utils/RxSpyGroup.cs deleted file mode 100644 index 004b393..0000000 --- a/RxSpy/Utils/RxSpyGroup.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using RxSpy.Observables; - -namespace RxSpy -{ - public class RxSpyGroup - { - [ThreadStatic] - internal static bool IsActive = false; - - public static IObservable Create(string name, Func> factory) - { - if (RxSpySession.Current == null) - return factory(); - - try - { - IsActive = true; - return new OperatorObservable(RxSpySession.Current, factory(), new OperatorInfo(name)); - } - finally - { - IsActive = false; - } - } - } -} From d1f49d472359b2c378476659eca98faea855604f Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Mon, 15 Sep 2014 02:28:48 +0200 Subject: [PATCH 3/4] Initial hack for explicit capture --- RxSpy/Proxy/QueryServiceProxy.cs | 4 +-- RxSpy/RxSpySession.cs | 42 +++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/RxSpy/Proxy/QueryServiceProxy.cs b/RxSpy/Proxy/QueryServiceProxy.cs index 6e90c5d..2baa186 100644 --- a/RxSpy/Proxy/QueryServiceProxy.cs +++ b/RxSpy/Proxy/QueryServiceProxy.cs @@ -28,16 +28,14 @@ internal class QueryLanguageProxy : RealProxy, IRemotingTypeInfo readonly Type _queryLanguageType; readonly Type _queryLanguageInterface; readonly RxSpySession _session; - readonly bool _explicitCapture; - internal QueryLanguageProxy(RxSpySession session, object realQueryLanguage, bool explicitCapture) + internal QueryLanguageProxy(RxSpySession session, object realQueryLanguage) : base(typeof(ContextBoundObject)) { _queryLanguage = realQueryLanguage; _queryLanguageType = realQueryLanguage.GetType(); _queryLanguageInterface = _queryLanguageType.GetInterface("IQueryLanguage"); _session = session; - _explicitCapture = explicitCapture; } public override IMessage Invoke(IMessage msg) diff --git a/RxSpy/RxSpySession.cs b/RxSpy/RxSpySession.cs index c07e7a9..3c090ae 100644 --- a/RxSpy/RxSpySession.cs +++ b/RxSpy/RxSpySession.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Reactive; +using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reflection; using System.Threading; @@ -18,12 +19,25 @@ public class RxSpySession: IRxSpyEventHandler, IDisposable { static int _launched = 0; readonly IRxSpyEventHandler _eventHandler; + readonly bool _explicitCapture; + + [ThreadStatic] + bool _isInCaptureScope; + + public bool IsCapturing + { + get + { + return _explicitCapture == false || _isInCaptureScope == true; + } + } internal static RxSpySession Current { get; private set; } - RxSpySession(IRxSpyEventHandler eventHandler) + RxSpySession(IRxSpyEventHandler eventHandler, bool explicitCapture) { _eventHandler = eventHandler; + _explicitCapture = explicitCapture; } public static RxSpySession Launch(string pathToRxSpy = null, bool explicitCapture = false) @@ -51,18 +65,18 @@ public static RxSpySession Launch(TimeSpan timeout, string pathToRxSpy = null, b Process.Start(psi); server.WaitForConnection(timeout); - return Launch(server); + return Launch(server, explicitCapture); } public static RxSpySession Launch(IRxSpyEventHandler eventHandler, bool explicitCapture = false) { - var session = new RxSpySession(eventHandler); + var session = new RxSpySession(eventHandler, explicitCapture); Current = session; if (Interlocked.CompareExchange(ref _launched, 1, 0) != 0) throw new InvalidOperationException("Session already created"); - InstallInterceptingQueryLanguage(session, explicitCapture); + InstallInterceptingQueryLanguage(session); return session; } @@ -110,7 +124,7 @@ static string FindGuiPath(string explicitPathToRxSpy) throw new ArgumentException("Can't find RxSpy.LiveView.exe - either copy it and its DLLs to your output directory or pass in a path to Create"); } - static void InstallInterceptingQueryLanguage(RxSpySession session, bool explictCapture) + static void InstallInterceptingQueryLanguage(RxSpySession session) { // TODO: Verify that the version is supported var rxLinqAssembly = Assembly.Load(new AssemblyName("System.Reactive.Linq")); @@ -123,12 +137,28 @@ static void InstallInterceptingQueryLanguage(RxSpySession session, bool explictC var actualImplementation = defaultImplementationField.GetValue(null); - object proxy = new QueryLanguageProxy(session, actualImplementation, explictCapture) + object proxy = new QueryLanguageProxy(session, actualImplementation) .GetTransparentProxy(); defaultImplementationField.SetValue(null, proxy); } + public static IDisposable Capture() + { + Current.StartCapture(); + return Disposable.Create(() => Current.StopCapture()); + } + + public void StartCapture() + { + _isInCaptureScope = true; + } + + public void StopCapture() + { + _isInCaptureScope = false; + } + public void OnCreated(IOperatorCreatedEvent onCreatedEvent) { _eventHandler.OnCreated(onCreatedEvent); From a03e3af9db88ad9da20ad77b9db1dd9393ba80d1 Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Mon, 15 Sep 2014 02:43:50 +0200 Subject: [PATCH 4/4] Forward all calls while not capturing --- RxSpy/Proxy/QueryServiceProxy.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RxSpy/Proxy/QueryServiceProxy.cs b/RxSpy/Proxy/QueryServiceProxy.cs index 2baa186..ff4b1f6 100644 --- a/RxSpy/Proxy/QueryServiceProxy.cs +++ b/RxSpy/Proxy/QueryServiceProxy.cs @@ -45,6 +45,9 @@ public override IMessage Invoke(IMessage msg) if (call == null) throw new ArgumentException("QueryLanguageProxy only supports call messages"); + if (!RxSpySession.Current.IsCapturing) + return ForwardCall(call); + var method = (System.Reflection.MethodInfo)call.MethodBase; int skipFrames;