├── .nuget
├── NuGet.exe
└── NuGet.Config
├── tools
└── NuGet.exe
├── RxSpy.LiveView
├── Resources
│ └── rxspy.ico
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Communication
│ ├── IRxSpyClient.cs
│ └── RxSpyHttpClient.cs
├── ViewModels
│ ├── Graphs
│ │ ├── ObservableGraph.cs
│ │ ├── ObservableGraphLayout.cs
│ │ ├── ObserveableEdge.cs
│ │ └── ObservableVertex.cs
│ ├── RxSpyObservablesGridViewModel.cs
│ ├── ObservableGraphViewModel.cs
│ ├── RxSpyObservedValueViewModel.cs
│ ├── RxObservableDetailsViewModel.cs
│ ├── MainViewModel.cs
│ └── RxSpyObservableGridItemViewModel.cs
├── App.xaml.cs
├── MainWindow.xaml
├── App.xaml
├── Models
│ ├── RxSpyErrorModel.cs
│ ├── RxSpyObservedValueModel.cs
│ ├── RxSpySubscriptionModel.cs
│ ├── RxSpySessionModel.cs
│ └── RxSpyObservableModel.cs
├── MainWindow.xaml.cs
├── packages.config
├── Styles
│ ├── DataGrid.xaml
│ └── ReactiveUI.xaml
├── App.config
├── Views
│ ├── MainView.xaml
│ ├── MainView.xaml.cs
│ └── Controls
│ │ ├── ObservableDetails.xaml
│ │ ├── ObservableDetails.xaml.cs
│ │ ├── TrackedObservablesGrid.xaml.cs
│ │ └── TrackedObservablesGrid.xaml
├── GraphWindow.xaml.cs
├── AppStartup
│ └── StartupSequence.cs
└── GraphWindow.xaml
├── RxSpy.Shared
├── packages.config
├── Model
│ └── Events
│ │ ├── ConnectedEvent.cs
│ │ ├── OnCompletedEvent.cs
│ │ ├── UnsubscribeEvent.cs
│ │ ├── DisconnectedEvent.cs
│ │ ├── TypeInfo.cs
│ │ ├── SubscribeEvent.cs
│ │ ├── TagOperatorEvent.cs
│ │ ├── Event.cs
│ │ ├── MethodInfo.cs
│ │ ├── OnNextEvent.cs
│ │ ├── OnErrorEvent.cs
│ │ ├── OperatorCreatedEvent.cs
│ │ └── CallSite.cs
├── Properties
│ └── AssemblyInfo.cs
├── Communication
│ └── Serialization
│ │ └── RxSpyJsonSerializerStrategy.cs
└── RxSpy.Shared.csproj
├── RxSpy
├── Observables
│ ├── IConnection.cs
│ ├── IOperatorObservable.cs
│ ├── ConnectableOperatorConnection.cs
│ ├── ConnectableOperatorObservable.cs
│ ├── OperatorConnection.cs
│ └── OperatorObservable.cs
├── packages.config
├── Communication
│ ├── IRxSpyServer.cs
│ ├── Serialization
│ │ └── RxSpyJsonSerializerStrategy.cs
│ └── RxSpyHttpServer.cs
├── Events
│ ├── OnCompletedEvent.cs
│ ├── UnsubscribeEvent.cs
│ ├── EventType.cs
│ ├── ConnectedEvent.cs
│ ├── TypeInfo.cs
│ ├── DisconnectedEvent.cs
│ ├── SubscribeEvent.cs
│ ├── TagOperatorEvent.cs
│ ├── OperatorCreatedEvent.cs
│ ├── OnNextEvent.cs
│ ├── OnErrorEvent.cs
│ ├── CallSite.cs
│ ├── MethodInfo.cs
│ ├── Interfaces.cs
│ └── Event.cs
├── Extensions
│ ├── SpyObservableExtensions.cs
│ └── EventHandlerExtensions.cs
├── IRxSpyEventHandler.cs
├── Utils
│ ├── OperatorFactory.cs
│ ├── MethodInvoker.cs
│ ├── TypeUtils.cs
│ ├── ValueFormatter.cs
│ ├── DebuggerDisplayFormatter.cs
│ ├── CallSiteCache.cs
│ └── ConnectionFactory.cs
├── OperatorInfo.cs
├── Properties
│ └── AssemblyInfo.cs
├── RxSpyStreamWriter.cs
└── RxSpy.csproj
├── RxSpy.StressTest
├── packages.config
├── CustomObjectWithDebuggerDisplay.cs
├── App.config
├── StressTestStream.cs
├── Properties
│ └── AssemblyInfo.cs
├── StressTestEventHandler.cs
├── RxSpy.StressTest.csproj
└── Program.cs
├── RxSpy.TestConsole
├── packages.config
├── App.config
├── Properties
│ └── AssemblyInfo.cs
├── Program.cs
└── RxSpy.TestConsole.csproj
├── .gitattributes
├── RxSpy.nuspec
├── LICENSE
├── RxSpy-LiveView.nuspec
├── RxSpy.sln
├── Readme.md
└── .gitignore
/.nuget/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niik/RxSpy/HEAD/.nuget/NuGet.exe
--------------------------------------------------------------------------------
/tools/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niik/RxSpy/HEAD/tools/NuGet.exe
--------------------------------------------------------------------------------
/RxSpy.LiveView/Resources/rxspy.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niik/RxSpy/HEAD/RxSpy.LiveView/Resources/rxspy.ico
--------------------------------------------------------------------------------
/RxSpy.Shared/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RxSpy/Observables/IConnection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Observables
8 | {
9 | interface IConnection: IOperatorObservable
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/RxSpy/Observables/IOperatorObservable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Observables
8 | {
9 | public interface IOperatorObservable
10 | {
11 | OperatorInfo OperatorInfo { get; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/RxSpy/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/ConnectedEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class ConnectedEvent: Event, IConnectedEvent
11 | {
12 | public long OperatorId { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/RxSpy.StressTest/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/OnCompletedEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class OnCompletedEvent: Event, IOnCompletedEvent
11 | {
12 | public long OperatorId { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/UnsubscribeEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class UnsubscribeEvent: Event, IUnsubscribeEvent
11 | {
12 | public long SubscriptionId { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/RxSpy.TestConsole/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/DisconnectedEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class DisconnectedEvent : Event, IDisconnectedEvent
11 | {
12 | public long ConnectionId { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Communication/IRxSpyClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using ReactiveUI;
7 | using RxSpy.Events;
8 |
9 | namespace RxSpy.Communication
10 | {
11 | public interface IRxSpyClient
12 | {
13 | IObservable Connect(Uri address, TimeSpan timeout);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/TypeInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class TypeInfo: ITypeInfo
11 | {
12 | public string Name { get; set; }
13 | public string Namespace { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/ViewModels/Graphs/ObservableGraph.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using GraphSharp;
7 | using QuickGraph;
8 | using RxSpy.Models;
9 |
10 | namespace RxSpy.ViewModels.Graphs
11 | {
12 | public class ObservableGraph : BidirectionalGraph
13 | {
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/ViewModels/Graphs/ObservableGraphLayout.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using GraphSharp.Controls;
7 | using RxSpy.Models;
8 |
9 | namespace RxSpy.ViewModels.Graphs
10 | {
11 | public class ObservableGraphLayout: GraphLayout
12 | {
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/SubscribeEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class SubscribeEvent : Event, ISubscribeEvent
11 | {
12 | public long ChildId { get; set; }
13 | public long ParentId { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/TagOperatorEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class TagOperatorEvent: Event, ITagOperatorEvent
11 | {
12 | public long OperatorId { get; set; }
13 | public string Tag { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/Event.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class Event: IEvent
11 | {
12 | public EventType EventType { get; set; }
13 | public long EventId { get; set; }
14 | public long EventTime { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/RxSpy/Communication/IRxSpyServer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Communication
9 | {
10 | internal interface IRxSpyServer: IDisposable
11 | {
12 | Uri Address { get; }
13 |
14 | void WaitForConnection(TimeSpan timeout);
15 | void EnqueueEvent(IEvent ev);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RxSpy.StressTest/CustomObjectWithDebuggerDisplay.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace RxSpy.StressTest
9 | {
10 | [DebuggerDisplay("{Name} {Value,nq}")]
11 | public class CustomObjectWithDebuggerDisplay
12 | {
13 | public string Name { get; set; }
14 | public string Value { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/RxSpy/Communication/Serialization/RxSpyJsonSerializerStrategy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Communication.Serialization
8 | {
9 | public class RxSpyJsonSerializerStrategy: PocoJsonSerializerStrategy
10 | {
11 | protected override object SerializeEnum(Enum p)
12 | {
13 | return Enum.GetName(p.GetType(), p);
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/MethodInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class MethodInfo: IMethodInfo
11 | {
12 | public string DeclaringType { get; set; }
13 | public string Name { get; set; }
14 | public string Namespace { get; set; }
15 | public string Signature { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/OnNextEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class OnNextEvent: Event, IOnNextEvent
11 | {
12 | public long OperatorId { get; set; }
13 | public string ValueType { get; set; }
14 | public string Value { get; set; }
15 | public int Thread { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RxSpy/Events/OnCompletedEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RxSpy.Events
7 | {
8 | internal class OnCompletedEvent : Event, IOnCompletedEvent
9 | {
10 | public long OperatorId { get; private set; }
11 |
12 | public OnCompletedEvent(OperatorInfo operatorInfo)
13 | : base(EventType.OnCompleted)
14 | {
15 | OperatorId = operatorInfo.Id;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/RxSpy/Events/UnsubscribeEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RxSpy.Events
7 | {
8 | internal class UnsubscribeEvent : Event, IUnsubscribeEvent
9 | {
10 | public long SubscriptionId { get; private set; }
11 |
12 | public UnsubscribeEvent(long subscriptionId)
13 | : base(EventType.Unsubscribe)
14 | {
15 | SubscriptionId = subscriptionId;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/RxSpy/Events/EventType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Events
8 | {
9 | public enum EventType
10 | {
11 | OperatorCreated,
12 | OperatorCollected,
13 | Subscribe,
14 | Unsubscribe,
15 |
16 | OnNext,
17 | OnError,
18 | OnCompleted,
19 |
20 | TagOperator,
21 |
22 | Connected,
23 | Disconnected
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/OnErrorEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class OnErrorEvent: Event, IOnErrorEvent
11 | {
12 | public ITypeInfo ErrorType { get; set; }
13 | public string Message { get; set; }
14 | public string StackTrace { get; set; }
15 | public long OperatorId { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RxSpy/Events/ConnectedEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Events
8 | {
9 | internal class ConnectedEvent : Event, IConnectedEvent
10 | {
11 | public long OperatorId { get; set; }
12 |
13 | public ConnectedEvent(OperatorInfo operatorInfo)
14 | : base(EventType.Connected)
15 | {
16 | OperatorId = operatorInfo.Id;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/RxSpy/Events/TypeInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Events
8 | {
9 | public class TypeInfo: ITypeInfo
10 | {
11 | public string Name { get; private set; }
12 | public string Namespace { get; private set; }
13 |
14 | public TypeInfo(Type type)
15 | {
16 | Name = type.Name;
17 | Namespace = type.Namespace;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/RxSpy/Events/DisconnectedEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Events
8 | {
9 | internal class DisconnectedEvent : Event, IDisconnectedEvent
10 | {
11 | public long ConnectionId { get; set; }
12 |
13 | public DisconnectedEvent(long connectionId)
14 | : base(EventType.Disconnected)
15 | {
16 | ConnectionId = connectionId;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/OperatorCreatedEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models.Events
9 | {
10 | public class OperatorCreatedEvent : Event, IOperatorCreatedEvent
11 | {
12 | public long Id { get; set; }
13 | public string Name { get; set; }
14 | public ICallSite CallSite { get; set; }
15 | public IMethodInfo OperatorMethod { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 | using System.Windows;
9 | using RxSpy.AppStartup;
10 |
11 | namespace RxSpy
12 | {
13 | ///
14 | /// Interaction logic for App.xaml
15 | ///
16 | public partial class App : Application
17 | {
18 | public App()
19 | {
20 | StartupSequence.Start();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/RxSpy/Events/SubscribeEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RxSpy.Events
7 | {
8 | internal class SubscribeEvent : Event, ISubscribeEvent
9 | {
10 | public long ChildId { get; private set; }
11 | public long ParentId { get; private set; }
12 |
13 | public SubscribeEvent(OperatorInfo child, OperatorInfo parent)
14 | : base(EventType.Subscribe)
15 | {
16 | ChildId = child.Id;
17 | ParentId = parent.Id;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/RxSpy/Events/TagOperatorEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Events
8 | {
9 | internal class TagOperatorEvent : Event, ITagOperatorEvent
10 | {
11 | public long OperatorId { get; set; }
12 | public string Tag { get; set; }
13 |
14 | public TagOperatorEvent(OperatorInfo info, string tag)
15 | : base(EventType.TagOperator)
16 | {
17 | OperatorId = info.Id;
18 | Tag = tag;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/RxSpy/Extensions/SpyObservableExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Observables;
7 |
8 | namespace System.Reactive.Linq
9 | {
10 | public static class SpyObservableExtensions
11 | {
12 | public static IObservable SpyTag(this IObservable source, string tag)
13 | {
14 | var oobs = source as OperatorObservable;
15 |
16 | if (oobs != null)
17 | oobs.Tag(tag);
18 |
19 | return source;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Models/RxSpyErrorModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using RxSpy.Events;
6 |
7 | namespace RxSpy.Models
8 | {
9 | public class RxSpyErrorModel
10 | {
11 | public ITypeInfo ErrorType { get; set; }
12 | public string Message { get; set; }
13 | public TimeSpan Received { get; set; }
14 | public string StackTrace { get; set; }
15 |
16 | public RxSpyErrorModel(IOnErrorEvent onErrorEvent)
17 | {
18 | Received = TimeSpan.FromMilliseconds(onErrorEvent.EventTime);
19 | ErrorType = onErrorEvent.ErrorType;
20 | Message = onErrorEvent.Message;
21 | StackTrace = onErrorEvent.StackTrace;
22 | }
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Models/RxSpyObservedValueModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy.Models
9 | {
10 | public class RxSpyObservedValueModel
11 | {
12 | public string ValueType { get; set; }
13 | public string Value { get; set; }
14 | public TimeSpan Received { get; set; }
15 | public int Thread { get; set; }
16 |
17 | public RxSpyObservedValueModel(IOnNextEvent onNextEvent)
18 | {
19 | ValueType = onNextEvent.ValueType;
20 | Value = onNextEvent.Value;
21 | Thread = onNextEvent.Thread;
22 |
23 | Received = TimeSpan.FromMilliseconds(onNextEvent.EventTime);
24 | }
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/RxSpy/IRxSpyEventHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Events;
7 |
8 | namespace RxSpy
9 | {
10 | public interface IRxSpyEventHandler: IDisposable
11 | {
12 | void OnCreated(IOperatorCreatedEvent onCreatedEvent);
13 | void OnCompleted(IOnCompletedEvent onCompletedEvent);
14 | void OnError(IOnErrorEvent onErrorEvent);
15 | void OnNext(IOnNextEvent onNextEvent);
16 | void OnSubscribe(ISubscribeEvent subscribeEvent);
17 | void OnUnsubscribe(IUnsubscribeEvent unsubscribeEvent);
18 | void OnConnected(IConnectedEvent connectedEvent);
19 | void OnDisconnected(IDisconnectedEvent disconnectedEvent);
20 | void OnTag(ITagOperatorEvent tagEvent);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/RxSpy/Events/OperatorCreatedEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RxSpy.Events
8 | {
9 | internal class OperatorCreatedEvent : Event, IOperatorCreatedEvent
10 | {
11 | readonly OperatorInfo _operatorInfo;
12 |
13 | public long Id { get { return _operatorInfo.Id; } }
14 | public string Name { get { return _operatorInfo.Name; } }
15 | public ICallSite CallSite { get { return _operatorInfo.CallSite; } }
16 | public IMethodInfo OperatorMethod { get { return _operatorInfo.OperatorMethod; } }
17 |
18 | public OperatorCreatedEvent(OperatorInfo operatorInfo)
19 | : base(EventType.OperatorCreated)
20 | {
21 | _operatorInfo = operatorInfo;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/RxSpy/Events/OnNextEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Utils;
7 |
8 | namespace RxSpy.Events
9 | {
10 | internal class OnNextEvent : Event, IOnNextEvent
11 | {
12 | public long OperatorId { get; private set; }
13 | public string ValueType { get; private set; }
14 | public string Value { get; private set; }
15 | public int Thread { get; private set; }
16 |
17 | public OnNextEvent(OperatorInfo operatorInfo, Type valueType, object value, int thread)
18 | : base(EventType.OnNext)
19 | {
20 | OperatorId = operatorInfo.Id;
21 | ValueType = TypeUtils.ToFriendlyName(valueType);
22 | Value = ValueFormatter.ToString(value, valueType);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/RxSpy/Events/OnErrorEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RxSpy.Events
7 | {
8 | internal class OnErrorEvent : Event, IOnErrorEvent
9 | {
10 | public ITypeInfo ErrorType { get; private set; }
11 | public string Message { get; private set; }
12 | public long OperatorId { get; private set; }
13 | public string StackTrace { get; private set; }
14 |
15 | public OnErrorEvent(OperatorInfo operatorInfo, Exception error)
16 | : base(EventType.OnError)
17 | {
18 | if (error == null)
19 | return;
20 |
21 | OperatorId = operatorInfo.Id;
22 | ErrorType = new TypeInfo(error.GetType());
23 | Message = error.Message;
24 | StackTrace = error.StackTrace;
25 | }
26 |
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/RxSpy/Events/CallSite.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace RxSpy.Events
10 | {
11 | public class CallSite : ICallSite
12 | {
13 | public int Line { get; private set; }
14 | public string File { get; private set; }
15 | public int ILOffset { get; private set; }
16 | public IMethodInfo Method { get; private set; }
17 |
18 | public CallSite(StackFrame frame)
19 | {
20 | Line = frame.GetFileLineNumber();
21 | File = frame.GetFileName();
22 | ILOffset = frame.GetILOffset();
23 |
24 | var method = frame.GetMethod();
25 |
26 | if (method != null)
27 | Method = new MethodInfo(method);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Model/Events/CallSite.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using RxSpy.Events;
8 |
9 | namespace RxSpy.Models.Events
10 | {
11 | public class CallSite : ICallSite
12 | {
13 | public string File { get; set; }
14 | public int ILOffset { get; set; }
15 | public int Line { get; set; }
16 | public IMethodInfo Method { get; set; }
17 |
18 | public override string ToString()
19 | {
20 | if (Method.Name == null)
21 | return "";
22 |
23 | string typeAndMethod = Method.DeclaringType + "." + Method.Signature;
24 |
25 | if (File != null && Line != -1)
26 | return typeAndMethod + " in " + Path.GetFileName(File) + ":" + Line;
27 |
28 | return typeAndMethod;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/ViewModels/Graphs/ObserveableEdge.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using QuickGraph;
8 | using RxSpy.Models;
9 |
10 | namespace RxSpy.ViewModels.Graphs
11 | {
12 | [DebuggerDisplay("{Source} -> {Target}")]
13 | public class ObserveableEdge : Edge, IEquatable
14 | {
15 | public ObserveableEdge(ObservableVertex child, ObservableVertex parent)
16 | : base(child, parent)
17 | {
18 |
19 | }
20 |
21 | public bool Equals(ObserveableEdge other)
22 | {
23 | if (other == null) return false;
24 |
25 | return other.Source.Equals(Source) && other.Target.Equals(Target);
26 | }
27 |
28 | public override int GetHashCode()
29 | {
30 | return Source.GetHashCode() ^ Target.GetHashCode();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/RxSpy.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RxSpy
5 | 0.1.5
6 | A library that provides logging/analysis of Reactive Extensions observables, events, errors and subscriptions in your application.
7 | Markus Olsson
8 | https://github.com/niik/RxSpy
9 | https://github.com/niik/RxSpy/blob/master/LICENSE
10 | en-us
11 | false
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 | using ReactiveUI;
16 | using RxSpy.ViewModels;
17 | using Splat;
18 |
19 | namespace RxSpy
20 | {
21 | ///
22 | /// Interaction logic for MainWindow.xaml
23 | ///
24 | public partial class MainWindow : Window
25 | {
26 | public MainWindow()
27 | {
28 | InitializeComponent();
29 |
30 | viewHost.ViewModel = Locator.Current.GetService();
31 | }
32 |
33 | protected override void OnClosed(EventArgs e)
34 | {
35 | base.OnClosed(e);
36 | Application.Current.Shutdown();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/RxSpy.StressTest/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/RxSpy.TestConsole/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/RxSpy/Observables/ConnectableOperatorConnection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Reactive.Disposables;
4 | using System.Reactive.Subjects;
5 | using RxSpy.Events;
6 |
7 | namespace RxSpy.Observables
8 | {
9 | internal class ConnectableOperatorConnection : OperatorConnection, IConnectableObservable
10 | {
11 | readonly IConnectableObservable _connectableObservable;
12 |
13 | public ConnectableOperatorConnection(RxSpySession session, IConnectableObservable parent, OperatorInfo childInfo)
14 | : base(session, parent, childInfo)
15 | {
16 | _connectableObservable = parent;
17 | }
18 |
19 | public IDisposable Connect()
20 | {
21 | var connectionId = Session.OnConnected(OperatorInfo);
22 | var disp = _connectableObservable.Connect();
23 |
24 | return Disposable.Create(() =>
25 | {
26 | disp.Dispose();
27 | Session.OnDisconnected(Event.Disconnect(connectionId));
28 | });
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Markus Olsson
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a
4 | copy of this software and associated documentation files (the "Software"),
5 | to deal in the Software without restriction, including without limitation
6 | the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 | and/or sell copies of the Software, and to permit persons to whom the
8 | Software is furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 | DEALINGS IN THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/RxSpy/Observables/ConnectableOperatorObservable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Reactive.Disposables;
4 | using System.Reactive.Subjects;
5 | using RxSpy.Events;
6 |
7 | namespace RxSpy.Observables
8 | {
9 | internal class ConnectableOperatorObservable : OperatorObservable, IConnectableObservable
10 | {
11 | readonly IConnectableObservable _connectableObservable;
12 |
13 | public ConnectableOperatorObservable(RxSpySession session, IConnectableObservable parent, OperatorInfo operatorInfo)
14 | : base(session, parent, operatorInfo)
15 | {
16 | _connectableObservable = parent;
17 | }
18 |
19 | public IDisposable Connect()
20 | {
21 | var connectionId = Session.OnConnected(OperatorInfo);
22 | var disp = _connectableObservable.Connect();
23 |
24 | return Disposable.Create(() =>
25 | {
26 | disp.Dispose();
27 | Session.OnDisconnected(Event.Disconnect(connectionId));
28 | });
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18449
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace RxSpy.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/ViewModels/RxSpyObservablesGridViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Reactive.Linq;
6 | using System.Threading.Tasks;
7 | using ReactiveUI;
8 | using RxSpy.Models;
9 |
10 | namespace RxSpy.ViewModels
11 | {
12 | public class RxSpyObservablesGridViewModel : ReactiveObject
13 | {
14 | IReactiveDerivedList _observables;
15 | public IReactiveDerivedList Observables
16 | {
17 | get { return _observables; }
18 | set { this.RaiseAndSetIfChanged(ref _observables, value); }
19 | }
20 |
21 | RxSpyObservableGridItemViewModel _selectedItem;
22 | public RxSpyObservableGridItemViewModel SelectedItem
23 | {
24 | get { return _selectedItem; }
25 | set { this.RaiseAndSetIfChanged(ref _selectedItem, value); }
26 | }
27 |
28 | public RxSpyObservablesGridViewModel(IReadOnlyReactiveList model)
29 | {
30 | Observables = model.CreateDerivedCollection(x => new RxSpyObservableGridItemViewModel(x));
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Styles/DataGrid.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/RxSpy-LiveView.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RxSpy.LiveView
5 | RxSpy with LiveView
6 | 0.1.5
7 | RxSpy bundled with a graphical interfaces for inspecting reactive applications. The LiveView interface will not be shipped alongside your application.
8 | Markus Olsson
9 | https://github.com/niik/RxSpy
10 | https://github.com/niik/RxSpy/blob/master/LICENSE
11 | en-us
12 | false
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/RxSpy/Extensions/EventHandlerExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Communication;
7 | using RxSpy.Events;
8 |
9 | namespace RxSpy.Events
10 | {
11 | public static class EventHandlerExtensions
12 | {
13 | static long Publish(Action publishAction, T ev) where T: IEvent
14 | {
15 | publishAction(ev);
16 | return ev.EventId;
17 | }
18 |
19 | public static long OnConnected(this IRxSpyEventHandler This, OperatorInfo operatorInfo)
20 | {
21 | return Publish(This.OnConnected, Event.Connect(operatorInfo));
22 | }
23 |
24 | public static long OnDisconnected(this IRxSpyEventHandler This, long subscriptionId)
25 | {
26 | return Publish(This.OnDisconnected, Event.Disconnect(subscriptionId));
27 | }
28 |
29 | public static long OnSubscribe(this IRxSpyEventHandler This, OperatorInfo child, OperatorInfo parent)
30 | {
31 | return Publish(This.OnSubscribe, Event.Subscribe(child, parent));
32 | }
33 |
34 | public static long OnUnsubscribe(this IRxSpyEventHandler This, long subscriptionId)
35 | {
36 | return Publish(This.OnUnsubscribe, Event.Unsubscribe(subscriptionId));
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/RxSpy/Utils/OperatorFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using RxSpy.Observables;
9 |
10 | namespace RxSpy.Utils
11 | {
12 | public static class OperatorFactory
13 | {
14 | readonly static ConcurrentDictionary> _connectionConstructorCache =
15 | new ConcurrentDictionary>();
16 |
17 |
18 | public static object CreateOperatorObservable(object source, Type signalType, OperatorInfo operatorInfo)
19 | {
20 | var ctor = _connectionConstructorCache.GetOrAdd(
21 | signalType,
22 | _ => new Lazy(() => GetOperatorConstructor(signalType)));
23 |
24 | return ctor.Value.Invoke(new object[] { RxSpySession.Current, source, operatorInfo });
25 | }
26 |
27 | static ConstructorInfo GetOperatorConstructor(Type signalType)
28 | {
29 | var operatorObservable = typeof(OperatorObservable<>).MakeGenericType(signalType);
30 |
31 | return operatorObservable.GetConstructor(new[] {
32 | typeof(RxSpySession),
33 | typeof(IObservable<>).MakeGenericType(signalType),
34 | typeof(OperatorInfo)
35 | });
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/RxSpy.StressTest/StressTestStream.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace RxSpy.StressTest
9 | {
10 | public class StressTestStream: Stream
11 | {
12 | public override bool CanRead
13 | {
14 | get { return false; }
15 | }
16 |
17 | public override bool CanSeek
18 | {
19 | get { return false; }
20 | }
21 |
22 | public override bool CanWrite
23 | {
24 | get { return true; }
25 | }
26 |
27 | public override void Flush()
28 | {
29 | }
30 |
31 | public override long Length
32 | {
33 | get { return Position; }
34 | }
35 |
36 | public override long Position { get; set; }
37 |
38 | public override int Read(byte[] buffer, int offset, int count)
39 | {
40 | throw new NotImplementedException();
41 | }
42 |
43 | public override long Seek(long offset, SeekOrigin origin)
44 | {
45 | throw new NotImplementedException();
46 | }
47 |
48 | public override void SetLength(long value)
49 | {
50 | throw new NotImplementedException();
51 | }
52 |
53 | public override void Write(byte[] buffer, int offset, int count)
54 | {
55 | Position += count;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Models/RxSpySubscriptionModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using ReactiveUI;
7 | using RxSpy.Events;
8 |
9 | namespace RxSpy.Models
10 | {
11 | public class RxSpySubscriptionModel: ReactiveObject
12 | {
13 | public long SubscriptionId { get; set; }
14 |
15 | RxSpyObservableModel _parent;
16 | public RxSpyObservableModel Parent
17 | {
18 | get { return _parent; }
19 | set { this.RaiseAndSetIfChanged(ref _parent, value); }
20 | }
21 |
22 | RxSpyObservableModel _child;
23 | public RxSpyObservableModel Child
24 | {
25 | get { return _child; }
26 | set { this.RaiseAndSetIfChanged(ref _child, value); }
27 | }
28 |
29 | bool _isActive;
30 | public bool IsActive
31 | {
32 | get { return _isActive; }
33 | set { this.RaiseAndSetIfChanged(ref _isActive, value); }
34 | }
35 |
36 | public TimeSpan Created { get; set; }
37 |
38 | public RxSpySubscriptionModel(ISubscribeEvent subscribeEvent, RxSpyObservableModel child, RxSpyObservableModel parent)
39 | {
40 | SubscriptionId = subscribeEvent.EventId;
41 | Parent = parent;
42 | Child = child;
43 | IsActive = true;
44 | Created = TimeSpan.FromMilliseconds(subscribeEvent.EventTime);
45 | }
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/RxSpy/OperatorInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using RxSpy.Events;
3 |
4 | namespace RxSpy
5 | {
6 | public class OperatorInfo
7 | {
8 | static long idCounter = 0;
9 |
10 | readonly string _name;
11 | readonly bool _anonymous;
12 | readonly long _id;
13 | readonly string _friendlyName;
14 | readonly CallSite _callSite;
15 | readonly MethodInfo _operatorMethod;
16 |
17 | public string Name { get { return _name; } }
18 | public long Id { get { return _id; } }
19 | public CallSite CallSite { get { return _callSite; } }
20 | public MethodInfo OperatorMethod { get { return _operatorMethod; } }
21 | public bool IsAnonymous { get { return _anonymous; } }
22 |
23 | internal OperatorInfo(CallSite callSite, MethodInfo operatorMethod)
24 | {
25 | _id = Interlocked.Increment(ref idCounter);
26 |
27 | _callSite = callSite;
28 | _operatorMethod = operatorMethod;
29 |
30 | _name = _operatorMethod.Name;
31 | _friendlyName = _name + "#" + _id;
32 | _anonymous = false;
33 | }
34 |
35 | internal OperatorInfo(string name)
36 | {
37 | _id = Interlocked.Increment(ref idCounter);
38 | _name = name;
39 | _friendlyName = _name + "#" + _id;
40 | _anonymous = true;
41 | }
42 |
43 | public override string ToString()
44 | {
45 | return _friendlyName;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/RxSpy/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RxSpy")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RxSpy")]
13 | [assembly: AssemblyCopyright("Copyright © Markus Olsson 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ac70fb73-8c91-4713-ae06-c3fbd0832754")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("0.1.5")]
36 | [assembly: AssemblyFileVersion("0.1.5")]
37 |
--------------------------------------------------------------------------------
/RxSpy.Shared/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RxSpy.Shared")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RxSpy.Shared")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("3844c72a-8326-4098-b91b-1369e890249e")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/RxSpy.StressTest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RxSpy.StressTest")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RxSpy.StressTest")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("4dfdd957-a79e-49ff-a15d-6ec35c528f35")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/RxSpy.TestConsole/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RxSpy.TestConsole")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RxSpy.TestConsole")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("4a1131d3-6b93-4506-81ae-11f5d19f7d07")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Views/MainView.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | signals, errors. signals per second.
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Views/MainView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using ReactiveUI;
4 | using RxSpy.ViewModels;
5 |
6 | namespace RxSpy.Views
7 | {
8 | ///
9 | /// Interaction logic for MainView.xaml
10 | ///
11 | public partial class MainView : UserControl, IViewFor
12 | {
13 | public MainView()
14 | {
15 | InitializeComponent();
16 |
17 | DataContextChanged += (s, e) => ViewModel = e.NewValue as MainViewModel;
18 |
19 | this.OneWayBind(ViewModel, vm => vm.GridViewModel, v => v.observablesGrid.ViewModel);
20 | this.OneWayBind(ViewModel, vm => vm.DetailsViewModel, v => v.detailsView.ViewModel);
21 |
22 | this.OneWayBind(ViewModel, vm => vm.SignalsPerSecond, v => v.signalsPerSecond.Text);
23 | this.OneWayBind(ViewModel, vm => vm.SignalCount, v => v.signals.Text);
24 | this.OneWayBind(ViewModel, vm => vm.ErrorCount, v => v.errors.Text);
25 | }
26 |
27 | public MainViewModel ViewModel
28 | {
29 | get { return GetValue(ViewModelProperty) as MainViewModel; }
30 | set { SetValue(ViewModelProperty, value); }
31 | }
32 |
33 | public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
34 | "ViewModel",
35 | typeof(MainViewModel),
36 | typeof(MainView),
37 | new PropertyMetadata(null)
38 | );
39 |
40 | object IViewFor.ViewModel
41 | {
42 | get { return ViewModel; }
43 | set { ViewModel = value as MainViewModel; }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/GraphWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 | using ReactiveUI;
15 | using RxSpy.ViewModels;
16 |
17 | namespace RxSpy
18 | {
19 | ///
20 | /// Interaction logic for GraphWindow.xaml
21 | ///
22 | public partial class GraphWindow : Window, IViewFor
23 | {
24 | public GraphWindow()
25 | {
26 | InitializeComponent();
27 |
28 | DataContextChanged += (s, e) => ViewModel = e.NewValue as ObservableGraphViewModel;
29 |
30 | this.OneWayBind(ViewModel, vm => vm.Graph, v => v.graphLayout.Graph);
31 | }
32 |
33 | public ObservableGraphViewModel ViewModel
34 | {
35 | get { return GetValue(ViewModelProperty) as ObservableGraphViewModel; }
36 | set { SetValue(ViewModelProperty, value); }
37 | }
38 |
39 | public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
40 | "ViewModel",
41 | typeof(ObservableGraphViewModel),
42 | typeof(GraphWindow),
43 | new PropertyMetadata(null)
44 | );
45 |
46 | object IViewFor.ViewModel
47 | {
48 | get { return ViewModel; }
49 | set { ViewModel = value as ObservableGraphViewModel; }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/ViewModels/ObservableGraphViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using ReactiveUI;
7 | using RxSpy.Models;
8 | using RxSpy.ViewModels.Graphs;
9 |
10 | namespace RxSpy.ViewModels
11 | {
12 | public class ObservableGraphViewModel: ReactiveObject
13 | {
14 | ObservableGraph _graph;
15 | public ObservableGraph Graph
16 | {
17 | get { return _graph; }
18 | set { this.RaiseAndSetIfChanged(ref _graph, value); }
19 | }
20 |
21 | public ObservableGraphViewModel(RxSpyObservableModel model)
22 | {
23 | Graph = new ObservableGraph();
24 |
25 | var vertex = new ObservableVertex(model);
26 | Graph.AddVertex(vertex);
27 |
28 | AddAncestors(vertex);
29 | AddDescendants(vertex);
30 | }
31 |
32 | private void AddDescendants(ObservableVertex vertex)
33 | {
34 | foreach (var child in vertex.Model.Children)
35 | {
36 | var childVertex = new ObservableVertex(child);
37 |
38 | Graph.AddVerticesAndEdge(new ObserveableEdge(vertex, childVertex));
39 | AddDescendants(childVertex);
40 | }
41 | }
42 |
43 | void AddAncestors(ObservableVertex vertex)
44 | {
45 | foreach (var parent in vertex.Model.Parents)
46 | {
47 | var parentVertex = new ObservableVertex(parent);
48 |
49 | Graph.AddVerticesAndEdge(new ObserveableEdge(parentVertex, vertex));
50 | AddAncestors(parentVertex);
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/RxSpy.TestConsole/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Reactive.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using RxSpy.Utils;
9 |
10 | namespace RxSpy.TestConsole
11 | {
12 | class Program
13 | {
14 | [DebuggerDisplay("{foo,nq}")]
15 | class Dummy
16 | {
17 | string foo = "bar";
18 | }
19 |
20 | static void Main(string[] args)
21 | {
22 | RxSpySession.Launch();
23 |
24 | var dummy = new [] { "Foo", "Bar", "Baz" };
25 |
26 | while (true)
27 | {
28 | var obs1 = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1));
29 | var obs2 = obs1.Select(x => dummy[x % dummy.Length]);
30 | var obs3 = obs1.Select(x => "---");
31 |
32 | var obs4 = obs2.Where(x => x.StartsWith("B"));
33 | var obsErr = Observable.Throw(new InvalidOperationException()).Catch(Observable.Return(""));
34 |
35 | var toJoin = new List> { obs3, obs4, obsErr };
36 |
37 | var obs5 = Observable.CombineLatest(toJoin);
38 | var obs6 = obs5.Select(x => string.Join(", ", x));
39 |
40 | //using (obs.Subscribe())
41 | using (obs6.Subscribe(Console.WriteLine))
42 | {
43 | Console.ReadLine();
44 | Console.WriteLine("Disposing of all observables");
45 | }
46 |
47 | Console.WriteLine("Press enter to begin again");
48 | Console.ReadLine();
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/RxSpy/Observables/OperatorConnection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reactive.Disposables;
3 | using RxSpy.Events;
4 |
5 | namespace RxSpy.Observables
6 | {
7 | internal class OperatorConnection : IObservable, IOperatorObservable, IConnection
8 | {
9 | readonly OperatorInfo _childInfo;
10 | private IObservable _parent;
11 | private OperatorInfo _parentInfo;
12 | private RxSpySession _session;
13 |
14 | public OperatorInfo OperatorInfo { get { return _childInfo; } }
15 | protected RxSpySession Session { get { return _session; } }
16 |
17 | public OperatorConnection(RxSpySession session, IObservable parent, OperatorInfo childInfo)
18 | {
19 | _session = session;
20 | _parent = parent;
21 |
22 | var oobs = parent as IOperatorObservable;
23 |
24 | if (oobs != null)
25 | _parentInfo = oobs.OperatorInfo;
26 |
27 | _childInfo = childInfo;
28 | }
29 |
30 | public override string ToString()
31 | {
32 | return _childInfo.ToString() + "::Connection";
33 | }
34 |
35 | public virtual IDisposable Subscribe(IObserver observer)
36 | {
37 | // Parent is not a tracked observable.
38 | if (_parentInfo == null)
39 | {
40 | return _parent.Subscribe(observer);
41 | }
42 |
43 | var subscriptionId = _session.OnSubscribe(_childInfo, _parentInfo);
44 |
45 | var disp = _parent.Subscribe(observer);
46 |
47 | return Disposable.Create(() =>
48 | {
49 | disp.Dispose();
50 | _session.OnUnsubscribe(subscriptionId);
51 | });
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/ViewModels/RxSpyObservedValueViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using ReactiveUI;
7 | using RxSpy.Models;
8 |
9 | namespace RxSpy.ViewModels
10 | {
11 | public class RxSpyObservedValueViewModel: ReactiveObject
12 | {
13 | RxSpyObservedValueModel _model;
14 |
15 | readonly ObservableAsPropertyHelper _received;
16 | public TimeSpan Received
17 | {
18 | get { return _received.Value; }
19 | }
20 |
21 | readonly ObservableAsPropertyHelper _value;
22 | public string Value
23 | {
24 | get { return _value.Value; }
25 | }
26 |
27 | readonly ObservableAsPropertyHelper _valueType;
28 | public string ValueType
29 | {
30 | get { return _valueType.Value; }
31 | }
32 |
33 | readonly ObservableAsPropertyHelper _thread;
34 | public int Thread
35 | {
36 | get { return _thread.Value; }
37 | }
38 |
39 | public RxSpyObservedValueViewModel(RxSpyObservedValueModel model)
40 | {
41 | _model = model;
42 |
43 | this.WhenAnyValue(x => x._model.Received)
44 | .ToProperty(this, x => x.Received, out _received);
45 |
46 | this.WhenAnyValue(x => x._model.Value)
47 | .ToProperty(this, x => x.Value, out _value);
48 |
49 | this.WhenAnyValue(x => x._model.ValueType)
50 | .ToProperty(this, x => x.ValueType, out _valueType);
51 |
52 | this.WhenAnyValue(x => x._model.Thread)
53 | .ToProperty(this, x => x.Thread, out _thread);
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/RxSpy.LiveView/Views/Controls/ObservableDetails.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/RxSpy/Events/MethodInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RxSpy.Utils;
7 | using bcl = System.Reflection;
8 |
9 | namespace RxSpy.Events
10 | {
11 | public class MethodInfo: IMethodInfo
12 | {
13 | public string Namespace { get; private set; }
14 | public string DeclaringType { get; private set; }
15 | public string Name { get; private set; }
16 | public string Signature { get; private set; }
17 |
18 | public MethodInfo(bcl.MethodBase method)
19 | {
20 | Namespace = method.Name;
21 | DeclaringType = method.DeclaringType.Name;
22 | Name = GetName(method);
23 | Signature = Name + " (" + GetArguments(method) + ")";
24 | }
25 |
26 | string GetName(bcl.MethodBase method)
27 | {
28 | if (method.IsGenericMethod)
29 | {
30 | var genericArgs = method.GetGenericArguments();
31 | return method.Name + "<" + string.Join(", ", genericArgs.Select(TypeUtils.ToFriendlyName)) + ">";
32 | }
33 |
34 | return method.Name;
35 | }
36 |
37 | string GetArguments(bcl.MethodBase method)
38 | {
39 | var arguments = new List();
40 |
41 | foreach (var arg in method.GetParameters())
42 | {
43 | arguments.Add(GetArgument(arg));
44 | }
45 |
46 | return string.Join(", ", arguments);
47 | }
48 |
49 | string GetArgument(bcl.ParameterInfo arg)
50 | {
51 | if (arg.ParameterType.IsGenericParameter)
52 | {
53 | }
54 |
55 | return TypeUtils.ToFriendlyName(arg.ParameterType) + " " + arg.Name;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/RxSpy.LiveView/Views/Controls/ObservableDetails.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 | using ReactiveUI;
16 | using RxSpy.ViewModels;
17 |
18 | namespace RxSpy.Views.Controls
19 | {
20 | ///
21 | /// Interaction logic for ObservableDetails.xaml
22 | ///
23 | public partial class ObservableDetails : UserControl, IViewFor
24 | {
25 | public ObservableDetails()
26 | {
27 | InitializeComponent();
28 |
29 | this.OneWayBind(ViewModel, vm => vm.ObservedValues, v => v.observableValuesGrid.ItemsSource);
30 | this.OneWayBind(ViewModel, vm => vm.Parents, v => v.parentsView.ViewModel);
31 | this.OneWayBind(ViewModel, vm => vm.Children, v => v.childrenView.ViewModel);
32 | this.OneWayBind(ViewModel, vm => vm.ErrorText, v => v.errorText.Text);
33 | }
34 |
35 | public RxSpyObservableDetailsViewModel ViewModel
36 | {
37 | get { return GetValue(ViewModelProperty) as RxSpyObservableDetailsViewModel; }
38 | set { SetValue(ViewModelProperty, value); }
39 | }
40 |
41 | public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
42 | "ViewModel",
43 | typeof(RxSpyObservableDetailsViewModel),
44 | typeof(ObservableDetails),
45 | new PropertyMetadata(null)
46 | );
47 |
48 | object IViewFor.ViewModel
49 | {
50 | get { return ViewModel; }
51 | set { ViewModel = value as RxSpyObservableDetailsViewModel; }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/RxSpy/Utils/MethodInvoker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Reactive.Linq;
6 | using System.Reflection;
7 | using System.Reflection.Emit;
8 |
9 | namespace RxSpy.Utils
10 | {
11 | public static class MethodInvoker
12 | {
13 | readonly static ConcurrentDictionary>> _cache
14 | = new ConcurrentDictionary>>();
15 |
16 | public static object Invoke(object target, Type targetType, MethodInfo method, object[] args)
17 | {
18 | var invokeDelegate = _cache.GetOrAdd(
19 | method,
20 | _ => new Lazy>(() => CreateInvokeDelegate(targetType, method))
21 | );
22 |
23 | return invokeDelegate.Value(target, args);
24 | }
25 |
26 | static Func