Skip to content

Commit

Permalink
Reorganize SQLiteLogViewer to support cross-platform development
Browse files Browse the repository at this point in the history
- Split Models and ViewModels out of the main project
- Use EventAggregator to eliminate ViewModels' WPF dependency
  • Loading branch information
Russell Johnston committed Aug 2, 2016
1 parent eb2a14f commit 5677824
Show file tree
Hide file tree
Showing 38 changed files with 445 additions and 151 deletions.
26 changes: 0 additions & 26 deletions MainWindow.xaml.cs

This file was deleted.

15 changes: 11 additions & 4 deletions SQLiteTracer.sln
Expand Up @@ -3,18 +3,20 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLiteDebugger", "SQLiteDebugger\SQLiteDebugger.csproj", "{756C15D9-F08D-4BDF-A24E-7923C20730CC}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLiteDebugger", "Source\SQLiteDebugger\SQLiteDebugger.csproj", "{756C15D9-F08D-4BDF-A24E-7923C20730CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLiteLogViewer", "SQLiteLogViewer.csproj", "{E46B981A-1FAA-497B-878C-2A5E9F1C56A1}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLiteLogViewer", "Source\Windows\SQLiteLogViewer.csproj", "{E46B981A-1FAA-497B-878C-2A5E9F1C56A1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models", "Models\Models.csproj", "{E9B05E2D-3775-4DFE-A149-4EBA92290623}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models", "Source\Models\Models.csproj", "{E9B05E2D-3775-4DFE-A149-4EBA92290623}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViewModels", "ViewModels\ViewModels.csproj", "{8E302C60-9E79-4CA6-86A4-76ED5A48B1DD}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViewModels", "Source\ViewModels\ViewModels.csproj", "{8E302C60-9E79-4CA6-86A4-76ED5A48B1DD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LogViewer", "LogViewer", "{B39E1675-4C89-4AB0-A781-74B43D1D03A9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{47D1DA0E-B407-4066-BFF3-BE6834641318}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Toolkit", "Source\Toolkit\Toolkit.csproj", "{9FBC79A6-CA1A-4B58-BDE8-088E5429DB0B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -37,6 +39,10 @@ Global
{8E302C60-9E79-4CA6-86A4-76ED5A48B1DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E302C60-9E79-4CA6-86A4-76ED5A48B1DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E302C60-9E79-4CA6-86A4-76ED5A48B1DD}.Release|Any CPU.Build.0 = Release|Any CPU
{9FBC79A6-CA1A-4B58-BDE8-088E5429DB0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FBC79A6-CA1A-4B58-BDE8-088E5429DB0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FBC79A6-CA1A-4B58-BDE8-088E5429DB0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FBC79A6-CA1A-4B58-BDE8-088E5429DB0B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -45,5 +51,6 @@ Global
{756C15D9-F08D-4BDF-A24E-7923C20730CC} = {47D1DA0E-B407-4066-BFF3-BE6834641318}
{E9B05E2D-3775-4DFE-A149-4EBA92290623} = {B39E1675-4C89-4AB0-A781-74B43D1D03A9}
{8E302C60-9E79-4CA6-86A4-76ED5A48B1DD} = {B39E1675-4C89-4AB0-A781-74B43D1D03A9}
{9FBC79A6-CA1A-4B58-BDE8-088E5429DB0B} = {B39E1675-4C89-4AB0-A781-74B43D1D03A9}
EndGlobalSection
EndGlobal
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 6 additions & 0 deletions Source/SQLiteDebugger/ConnectEvent.cs
@@ -0,0 +1,6 @@
namespace SQLiteDebugger
{
public class ConnectEvent
{
}
}
@@ -1,22 +1,26 @@
namespace SQLiteDebugger
{
using Toolkit;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

public class DebugClient
{
private EventAggregator events;

private BinaryWriter clientWriter;
private Task connectTask;

public DebugClient(EventAggregator events)
{
this.events = events;
}

public void Connect(string address, int port)
{
if (Uri.CheckHostName(address) == UriHostNameType.Unknown)
Expand All @@ -32,19 +36,13 @@ public void Connect(string address, int port)
this.connectTask = this.ConnectToServer(address, port);
}

public event EventHandler<EventArgs> Connected;

public event EventHandler<LogEventArgs> LogReceived;

public event EventHandler<TraceEventArgs> TraceReceived;

public event EventHandler<ProfileEventArgs> ProfileReceived;

public void SendOptions(bool plan, bool results, bool pause)
{
var data = new OptionsMessage
{
Plan = plan, Results = results, Pause = pause
Plan = plan,
Results = results,
Pause = pause
};

var json = JsonConvert.SerializeObject(data);
Expand Down Expand Up @@ -88,11 +86,7 @@ private async Task ConnectToServer(string address, int port)
await client.ConnectAsync(address, port);
this.clientWriter = new BinaryWriter(client.GetStream());

var handler = this.Connected;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
this.events.Publish<ConnectEvent>(new ConnectEvent());

await Task.Run(() => this.ReceiveMessages(client));
}
Expand Down Expand Up @@ -130,71 +124,26 @@ private void ReceiveMessages(TcpClient client)
{
case LogMessage.Type:
var logMessage = serializer.Deserialize<LogMessage>(jsonReader);
this.OnLogReceived(logMessage);
this.events.Publish<LogMessage>(logMessage);
break;

case TraceMessage.Type:
var traceMessage = serializer.Deserialize<TraceMessage>(jsonReader);
this.OnTraceReceived(traceMessage);
this.events.Publish<TraceMessage>(traceMessage);
break;

case ProfileMessage.Type:
var profileMessage = serializer.Deserialize<ProfileMessage>(jsonReader);
this.OnProfileReceived(profileMessage);
this.events.Publish<ProfileMessage>(profileMessage);
break;

default:
var errorMessage = new LogMessage { Message = message.ToString() };
this.OnLogReceived(errorMessage);
this.events.Publish<LogMessage>(errorMessage);
break;
}
}
}
}

private void OnLogReceived(LogMessage message)
{
var handler = this.LogReceived;
if (handler != null)
{
handler(this, new LogEventArgs { Message = message });
}
}

private void OnTraceReceived(TraceMessage message)
{
var handler = this.TraceReceived;
if (handler != null)
{
handler(this, new TraceEventArgs { Message = message });
}
}

private void OnProfileReceived(ProfileMessage message)
{
var handler = this.ProfileReceived;
if (handler != null)
{
handler(this, new ProfileEventArgs { Message = message });
}
}
}

[SuppressMessage("Microsoft.StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "EventArgs")]
public class LogEventArgs : EventArgs
{
public LogMessage Message { get; set; }
}

[SuppressMessage("Microsoft.StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "EventArgs")]
public class TraceEventArgs : EventArgs
{
public TraceMessage Message { get; set; }
}

[SuppressMessage("Microsoft.StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "EventArgs")]
public class ProfileEventArgs : EventArgs
{
public ProfileMessage Message { get; set; }
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Expand Up @@ -32,7 +32,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand All @@ -45,6 +45,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConnectEvent.cs" />
<Compile Include="DebugClient.cs" />
<Compile Include="Protocol\OptionsMessage.cs" />
<Compile Include="Protocol\ProfileMessage.cs" />
Expand All @@ -59,6 +60,12 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Toolkit\Toolkit.csproj">
<Project>{9fbc79a6-ca1a-4b58-bde8-088e5429db0b}</Project>
<Name>Toolkit</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand All @@ -67,4 +74,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
File renamed without changes.
File renamed without changes.
File renamed without changes.
Expand Up @@ -4,7 +4,7 @@
// </copyright>
// -----------------------------------------------------------------------

namespace SQLiteLogViewer
namespace Toolkit
{
using System;
using System.Windows.Input;
Expand Down
90 changes: 90 additions & 0 deletions Source/Toolkit/EventAggregator/DelegateWrapper.cs
@@ -0,0 +1,90 @@
// -----------------------------------------------------------------------
// <copyright file="DelegateWrapper.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

namespace Toolkit
{
using System;
using System.Reflection;

internal class DelegateWrapper
{
private WeakReference target;
private MethodInfo method;
private Type type;

private ThreadAffinity affinity;

public DelegateWrapper(Delegate wrappedDelegate, ThreadAffinity affinity)
{
this.target = new WeakReference(wrappedDelegate.Target);
this.method = wrappedDelegate.GetMethodInfo();
this.type = wrappedDelegate.GetType();

this.affinity = affinity;
}

public bool IsDead
{
get { return this.target.Target == null; }
}

public bool Wraps(Delegate wrappedDelegate)
{
return wrappedDelegate.Equals(this.TryGetDelegate());
}

public Invoker<TMessage> GetInvoker<TMessage>()
{
var action = this.TryGetDelegate();
if (action != null)
{
return new Invoker<TMessage>((Action<TMessage>)action, this.affinity);
}

return null;
}

public class Invoker<TMessage>
{
private Action<TMessage> action;
private ThreadAffinity affinity;

public Invoker(Action<TMessage> action, ThreadAffinity affinity)
{
this.action = action;
this.affinity = affinity;
}

public void Invoke(TMessage message, IDispatcher dispatcher)
{
if (this.affinity == ThreadAffinity.UIThread)
{
dispatcher.Invoke(() => this.action(message));
}
else
{
this.action(message);
}
}
}

private Delegate TryGetDelegate()
{
if (this.method.IsStatic)
{
return this.method.CreateDelegate(this.type, null);
}

var receiver = this.target.Target;
if (this.target != null)
{
return this.method.CreateDelegate(this.type, receiver);
}

return null;
}
}
}

0 comments on commit 5677824

Please sign in to comment.