From 69dc3aca0b9e7f492c68f6d97f8618d778983671 Mon Sep 17 00:00:00 2001 From: SmallChi <564952747@qq.com> Date: Wed, 20 Mar 2019 21:02:45 +0800 Subject: [PATCH] =?UTF-8?q?1.=E8=B0=83=E6=95=B4=E9=87=8D=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=202.=E4=BF=AE=E5=A4=8D=E8=AE=BE=E8=AE=A1=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=203.=E5=A2=9E=E5=8A=A0808=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=E8=B0=83=E7=94=A8=EF=BC=88=E5=BE=85=E5=81=9A=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/img/design_model.png | Bin 40162 -> 41589 bytes .../JT808.DotNetty.Client.csproj | 11 ++++ src/JT808.DotNetty.Client/JT808TcpClient.cs | 11 ++++ .../Enums/JT808ModeType.cs | 15 ++++++ .../Handlers/JT808MsgIdTcpHandlerBase.cs | 24 +++------ .../Handlers/JT808MsgIdUdpHandlerBase.cs | 21 +++----- .../JT808CoreDotnettyExtensions.cs | 31 +++++++++++ .../Jobs/JT808TcpAtomicCouterResetDailyJob.cs | 10 ++-- .../Jobs/JT808TcpTrafficResetDailyJob.cs | 10 ++-- .../Jobs/JT808UdpAtomicCouterResetDailyJob.cs | 10 ++-- .../Jobs/JT808UdpTrafficResetDailyJob.cs | 10 ++-- .../Metadata/JT808AtomicCounter.cs | 2 +- ...ervice.cs => JT808AtomicCounterService.cs} | 13 ++--- .../JT808AtomicCounterServiceFactory.cs | 30 +++++++++++ ...afficService.cs => JT808TrafficService.cs} | 12 +++-- .../Services/JT808TrafficServiceFactory.cs | 33 ++++++++++++ .../Services/JT808UdpAtomicCounterService.cs | 51 ------------------ .../Services/JT808UdpTrafficService.cs | 40 -------------- .../JT808UnificationTcpSendService.cs | 8 +-- .../JT808UnificationUdpSendService.cs | 8 +-- .../Handlers/JT808TcpServerHandler.cs | 16 +++--- .../JT808TcpDotnettyExtensions.cs | 2 - .../Handlers/JT808UdpServerHandler.cs | 28 +++++----- .../JT808UdpDotnettyExtensions.cs | 2 - .../JT808MsgIdDefaultWebApiHandler.cs | 39 +++++++------- .../JT808.DotNetty.WebApiClientTool.csproj | 2 +- src/JT808.DotNetty.sln | 6 +++ 27 files changed, 239 insertions(+), 206 deletions(-) create mode 100644 src/JT808.DotNetty.Client/JT808.DotNetty.Client.csproj create mode 100644 src/JT808.DotNetty.Client/JT808TcpClient.cs create mode 100644 src/JT808.DotNetty.Core/Enums/JT808ModeType.cs rename src/JT808.DotNetty.Core/Services/{JT808TcpAtomicCounterService.cs => JT808AtomicCounterService.cs} (69%) create mode 100644 src/JT808.DotNetty.Core/Services/JT808AtomicCounterServiceFactory.cs rename src/JT808.DotNetty.Core/Services/{JT808TcpTrafficService.cs => JT808TrafficService.cs} (68%) create mode 100644 src/JT808.DotNetty.Core/Services/JT808TrafficServiceFactory.cs delete mode 100644 src/JT808.DotNetty.Core/Services/JT808UdpAtomicCounterService.cs delete mode 100644 src/JT808.DotNetty.Core/Services/JT808UdpTrafficService.cs diff --git a/doc/img/design_model.png b/doc/img/design_model.png index eb9c7a98061928c6e44774baea902a153110d849..297e9aa962039cb1130cc645ec8f915e1588d644 100644 GIT binary patch literal 41589 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 CUG!-H diff --git a/src/JT808.DotNetty.Client/JT808.DotNetty.Client.csproj b/src/JT808.DotNetty.Client/JT808.DotNetty.Client.csproj new file mode 100644 index 0000000..91f9557 --- /dev/null +++ b/src/JT808.DotNetty.Client/JT808.DotNetty.Client.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/src/JT808.DotNetty.Client/JT808TcpClient.cs b/src/JT808.DotNetty.Client/JT808TcpClient.cs new file mode 100644 index 0000000..7a02dc5 --- /dev/null +++ b/src/JT808.DotNetty.Client/JT808TcpClient.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.DotNetty.Client +{ + public class JT808TcpClient + { + + } +} diff --git a/src/JT808.DotNetty.Core/Enums/JT808ModeType.cs b/src/JT808.DotNetty.Core/Enums/JT808ModeType.cs new file mode 100644 index 0000000..31d7473 --- /dev/null +++ b/src/JT808.DotNetty.Core/Enums/JT808ModeType.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.DotNetty.Core.Enums +{ + /// + /// 模式类型 + /// + public enum JT808ModeType + { + Tcp=1, + Udp = 2 + } +} diff --git a/src/JT808.DotNetty.Core/Handlers/JT808MsgIdTcpHandlerBase.cs b/src/JT808.DotNetty.Core/Handlers/JT808MsgIdTcpHandlerBase.cs index 67bca08..d6291e4 100644 --- a/src/JT808.DotNetty.Core/Handlers/JT808MsgIdTcpHandlerBase.cs +++ b/src/JT808.DotNetty.Core/Handlers/JT808MsgIdTcpHandlerBase.cs @@ -43,8 +43,7 @@ namespace JT808.DotNetty.Core.Handlers /// 平台无需回复 /// 实现自己的业务 /// - /// - /// + /// /// public virtual JT808Response Msg0x0001(JT808Request request) { @@ -53,8 +52,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 终端心跳 /// - /// - /// + /// /// public virtual JT808Response Msg0x0002(JT808Request request) { @@ -69,8 +67,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 终端注销 /// - /// - /// + /// /// public virtual JT808Response Msg0x0003(JT808Request request) { @@ -84,8 +81,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 终端注册 /// - /// - /// + /// /// public virtual JT808Response Msg0x0100(JT808Request request) { @@ -99,8 +95,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 终端鉴权 /// - /// - /// + /// /// public virtual JT808Response Msg0x0102(JT808Request request) { @@ -114,8 +109,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 位置信息汇报 /// - /// - /// + /// /// public virtual JT808Response Msg0x0200(JT808Request request) { @@ -129,8 +123,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 定位数据批量上传 /// - /// - /// + /// /// public virtual JT808Response Msg0x0704(JT808Request request) { @@ -144,8 +137,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 数据上行透传 /// - /// - /// + /// /// public virtual JT808Response Msg0x0900(JT808Request request) { diff --git a/src/JT808.DotNetty.Core/Handlers/JT808MsgIdUdpHandlerBase.cs b/src/JT808.DotNetty.Core/Handlers/JT808MsgIdUdpHandlerBase.cs index 5012734..44d9708 100644 --- a/src/JT808.DotNetty.Core/Handlers/JT808MsgIdUdpHandlerBase.cs +++ b/src/JT808.DotNetty.Core/Handlers/JT808MsgIdUdpHandlerBase.cs @@ -43,8 +43,7 @@ namespace JT808.DotNetty.Core.Handlers /// 平台无需回复 /// 实现自己的业务 /// - /// - /// + /// /// public virtual JT808Response Msg0x0001(JT808Request request) { @@ -53,8 +52,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 终端心跳 /// - /// - /// + /// /// public virtual JT808Response Msg0x0002(JT808Request request) { @@ -69,8 +67,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 终端注销 /// - /// - /// + /// /// public virtual JT808Response Msg0x0003(JT808Request request) { @@ -84,8 +81,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 终端注册 /// - /// - /// + /// /// public virtual JT808Response Msg0x0100(JT808Request request) { @@ -99,8 +95,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 终端鉴权 /// - /// - /// + /// /// public virtual JT808Response Msg0x0102(JT808Request request) { @@ -129,8 +124,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 定位数据批量上传 /// - /// - /// + /// /// public virtual JT808Response Msg0x0704(JT808Request request) { @@ -144,8 +138,7 @@ namespace JT808.DotNetty.Core.Handlers /// /// 数据上行透传 /// - /// - /// + /// /// public virtual JT808Response Msg0x0900(JT808Request request) { diff --git a/src/JT808.DotNetty.Core/JT808CoreDotnettyExtensions.cs b/src/JT808.DotNetty.Core/JT808CoreDotnettyExtensions.cs index b0da038..d48cac2 100644 --- a/src/JT808.DotNetty.Core/JT808CoreDotnettyExtensions.cs +++ b/src/JT808.DotNetty.Core/JT808CoreDotnettyExtensions.cs @@ -8,6 +8,7 @@ using JT808.DotNetty.Internal; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; using Newtonsoft.Json; using System; using System.Runtime.CompilerServices; @@ -16,6 +17,9 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("JT808.DotNetty.Tcp.Test")] [assembly: InternalsVisibleTo("JT808.DotNetty.Udp.Test")] [assembly: InternalsVisibleTo("JT808.DotNetty.WebApi.Test")] +[assembly: InternalsVisibleTo("JT808.DotNetty.Tcp")] +[assembly: InternalsVisibleTo("JT808.DotNetty.Udp")] +[assembly: InternalsVisibleTo("JT808.DotNetty.WebApi")] namespace JT808.DotNetty.Core { public static class JT808CoreDotnettyExtensions @@ -52,6 +56,33 @@ namespace JT808.DotNetty.Core serviceDescriptors.Configure(configuration.GetSection("JT808Configuration")); serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + return serviceDescriptors; + } + + public static IServiceCollection AddJT808Core(this IServiceCollection serviceDescriptors, Action jt808Options, Newtonsoft.Json.JsonSerializerSettings settings = null) + { + if (settings != null) + { + JsonConvert.DefaultSettings = new Func(() => + { + settings.Converters.Add(new JsonIPAddressConverter()); + settings.Converters.Add(new JsonIPEndPointConverter()); + settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + return settings; + }); + } + serviceDescriptors.Configure(jt808Options); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); + serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddSingleton(); diff --git a/src/JT808.DotNetty.Core/Jobs/JT808TcpAtomicCouterResetDailyJob.cs b/src/JT808.DotNetty.Core/Jobs/JT808TcpAtomicCouterResetDailyJob.cs index 06625bd..2211981 100644 --- a/src/JT808.DotNetty.Core/Jobs/JT808TcpAtomicCouterResetDailyJob.cs +++ b/src/JT808.DotNetty.Core/Jobs/JT808TcpAtomicCouterResetDailyJob.cs @@ -5,17 +5,17 @@ using System.Threading.Tasks; namespace JT808.DotNetty.Core.Jobs { - public class JT808TcpAtomicCouterResetDailyJob : JT808BackgroundService + internal class JT808TcpAtomicCouterResetDailyJob : JT808BackgroundService { private readonly ILogger _logger; - private readonly JT808TcpAtomicCounterService _jT808TcpAtomicCounterService; + private readonly JT808AtomicCounterService _jT808AtomicCounterService; public JT808TcpAtomicCouterResetDailyJob( - JT808TcpAtomicCounterService jT808TcpAtomicCounterService, + JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory, ILoggerFactory loggerFactory) { - _jT808TcpAtomicCounterService = jT808TcpAtomicCounterService; + _jT808AtomicCounterService = jT808AtomicCounterServiceFactory.Create(Enums.JT808ModeType.Tcp); _logger =loggerFactory.CreateLogger(); } @@ -28,7 +28,7 @@ namespace JT808.DotNetty.Core.Jobs while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation($"{ServiceName} task doing background work."); - _jT808TcpAtomicCounterService.Reset(); + _jT808AtomicCounterService.Reset(); await Task.Delay(DelayTimeSpan, stoppingToken); } _logger.LogInformation($"{ServiceName} background task is stopping."); diff --git a/src/JT808.DotNetty.Core/Jobs/JT808TcpTrafficResetDailyJob.cs b/src/JT808.DotNetty.Core/Jobs/JT808TcpTrafficResetDailyJob.cs index ca270fa..f90fc75 100644 --- a/src/JT808.DotNetty.Core/Jobs/JT808TcpTrafficResetDailyJob.cs +++ b/src/JT808.DotNetty.Core/Jobs/JT808TcpTrafficResetDailyJob.cs @@ -5,17 +5,17 @@ using System.Threading.Tasks; namespace JT808.DotNetty.Core.Jobs { - public class JT808TcpTrafficResetDailyJob : JT808BackgroundService + internal class JT808TcpTrafficResetDailyJob : JT808BackgroundService { private readonly ILogger _logger; - private readonly JT808TcpTrafficService _jT808TcpTrafficService; + private readonly JT808TrafficService _jT808TrafficService; public JT808TcpTrafficResetDailyJob( - JT808TcpTrafficService jT808TcpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, ILoggerFactory loggerFactory) { - _jT808TcpTrafficService = jT808TcpTrafficService; + _jT808TrafficService = jT808TrafficServiceFactory.Create( Enums.JT808ModeType.Tcp); _logger =loggerFactory.CreateLogger(); } @@ -28,7 +28,7 @@ namespace JT808.DotNetty.Core.Jobs while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation($"{ServiceName} task doing background work."); - _jT808TcpTrafficService.ResetSize(); + _jT808TrafficService.ResetSize(); await Task.Delay(DelayTimeSpan, stoppingToken); } _logger.LogInformation($"{ServiceName} background task is stopping."); diff --git a/src/JT808.DotNetty.Core/Jobs/JT808UdpAtomicCouterResetDailyJob.cs b/src/JT808.DotNetty.Core/Jobs/JT808UdpAtomicCouterResetDailyJob.cs index d609fdf..9e12afa 100644 --- a/src/JT808.DotNetty.Core/Jobs/JT808UdpAtomicCouterResetDailyJob.cs +++ b/src/JT808.DotNetty.Core/Jobs/JT808UdpAtomicCouterResetDailyJob.cs @@ -5,17 +5,17 @@ using System.Threading.Tasks; namespace JT808.DotNetty.Core.Jobs { - public class JT808UdpAtomicCouterResetDailyJob : JT808BackgroundService + internal class JT808UdpAtomicCouterResetDailyJob : JT808BackgroundService { private readonly ILogger _logger; - private readonly JT808UdpAtomicCounterService _jT808UdpAtomicCounterService; + private readonly JT808AtomicCounterService _jT808AtomicCounterService; public JT808UdpAtomicCouterResetDailyJob( - JT808UdpAtomicCounterService jT808UdpAtomicCounterService, + JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory, ILoggerFactory loggerFactory) { - _jT808UdpAtomicCounterService = jT808UdpAtomicCounterService; + _jT808AtomicCounterService = jT808AtomicCounterServiceFactory.Create(Enums.JT808ModeType.Udp); _logger =loggerFactory.CreateLogger(); } @@ -28,7 +28,7 @@ namespace JT808.DotNetty.Core.Jobs while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation($"{ServiceName} task doing background work."); - _jT808UdpAtomicCounterService.Reset(); + _jT808AtomicCounterService.Reset(); await Task.Delay(DelayTimeSpan, stoppingToken); } _logger.LogInformation($"{ServiceName} background task is stopping."); diff --git a/src/JT808.DotNetty.Core/Jobs/JT808UdpTrafficResetDailyJob.cs b/src/JT808.DotNetty.Core/Jobs/JT808UdpTrafficResetDailyJob.cs index 8641ac7..f9b9891 100644 --- a/src/JT808.DotNetty.Core/Jobs/JT808UdpTrafficResetDailyJob.cs +++ b/src/JT808.DotNetty.Core/Jobs/JT808UdpTrafficResetDailyJob.cs @@ -5,17 +5,17 @@ using System.Threading.Tasks; namespace JT808.DotNetty.Core.Jobs { - public class JT808UdpTrafficResetDailyJob : JT808BackgroundService + internal class JT808UdpTrafficResetDailyJob : JT808BackgroundService { private readonly ILogger _logger; - private readonly JT808UdpTrafficService _jT808UdpTrafficService; + private readonly JT808TrafficService _jT808TrafficService; public JT808UdpTrafficResetDailyJob( - JT808UdpTrafficService jT808UdpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, ILoggerFactory loggerFactory) { - _jT808UdpTrafficService = jT808UdpTrafficService; + _jT808TrafficService = jT808TrafficServiceFactory.Create(Enums.JT808ModeType.Udp); _logger =loggerFactory.CreateLogger(); } @@ -28,7 +28,7 @@ namespace JT808.DotNetty.Core.Jobs while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation($"{ServiceName} task doing background work."); - _jT808UdpTrafficService.ResetSize(); + _jT808TrafficService.ResetSize(); await Task.Delay(DelayTimeSpan, stoppingToken); } _logger.LogInformation($"{ServiceName} background task is stopping."); diff --git a/src/JT808.DotNetty.Core/Metadata/JT808AtomicCounter.cs b/src/JT808.DotNetty.Core/Metadata/JT808AtomicCounter.cs index 72bc92a..25b8cca 100644 --- a/src/JT808.DotNetty.Core/Metadata/JT808AtomicCounter.cs +++ b/src/JT808.DotNetty.Core/Metadata/JT808AtomicCounter.cs @@ -9,7 +9,7 @@ namespace JT808.DotNetty.Core.Metadata /// /// /// - public class JT808AtomicCounter + internal class JT808AtomicCounter { long counter = 0; diff --git a/src/JT808.DotNetty.Core/Services/JT808TcpAtomicCounterService.cs b/src/JT808.DotNetty.Core/Services/JT808AtomicCounterService.cs similarity index 69% rename from src/JT808.DotNetty.Core/Services/JT808TcpAtomicCounterService.cs rename to src/JT808.DotNetty.Core/Services/JT808AtomicCounterService.cs index 5c3fa0e..85cf0d5 100644 --- a/src/JT808.DotNetty.Core/Services/JT808TcpAtomicCounterService.cs +++ b/src/JT808.DotNetty.Core/Services/JT808AtomicCounterService.cs @@ -3,17 +3,18 @@ namespace JT808.DotNetty.Core.Services { /// - /// Tcp计数包服务 + /// 计数包服务 /// - public class JT808TcpAtomicCounterService + public class JT808AtomicCounterService { - private readonly JT808AtomicCounter MsgSuccessCounter = new JT808AtomicCounter(); + private readonly JT808AtomicCounter MsgSuccessCounter; - private readonly JT808AtomicCounter MsgFailCounter = new JT808AtomicCounter(); + private readonly JT808AtomicCounter MsgFailCounter; - public JT808TcpAtomicCounterService() + public JT808AtomicCounterService() { - + MsgSuccessCounter=new JT808AtomicCounter(); + MsgFailCounter = new JT808AtomicCounter(); } public void Reset() diff --git a/src/JT808.DotNetty.Core/Services/JT808AtomicCounterServiceFactory.cs b/src/JT808.DotNetty.Core/Services/JT808AtomicCounterServiceFactory.cs new file mode 100644 index 0000000..b3c30c4 --- /dev/null +++ b/src/JT808.DotNetty.Core/Services/JT808AtomicCounterServiceFactory.cs @@ -0,0 +1,30 @@ +using JT808.DotNetty.Core.Enums; +using System; +using System.Collections.Concurrent; + +namespace JT808.DotNetty.Core.Services +{ + public class JT808AtomicCounterServiceFactory + { + private readonly ConcurrentDictionary cache; + + private JT808AtomicCounterServiceFactory() + { + cache = new ConcurrentDictionary(); + } + + public JT808AtomicCounterService Create(JT808ModeType type) + { + if(cache.TryGetValue(type,out var service)) + { + return service; + } + else + { + var serviceNew = new JT808AtomicCounterService(); + cache.TryAdd(type, serviceNew); + return serviceNew; + } + } + } +} diff --git a/src/JT808.DotNetty.Core/Services/JT808TcpTrafficService.cs b/src/JT808.DotNetty.Core/Services/JT808TrafficService.cs similarity index 68% rename from src/JT808.DotNetty.Core/Services/JT808TcpTrafficService.cs rename to src/JT808.DotNetty.Core/Services/JT808TrafficService.cs index 3b9f737..6740ff8 100644 --- a/src/JT808.DotNetty.Core/Services/JT808TcpTrafficService.cs +++ b/src/JT808.DotNetty.Core/Services/JT808TrafficService.cs @@ -5,11 +5,17 @@ using System.Text; namespace JT808.DotNetty.Core.Services { - public class JT808TcpTrafficService + public class JT808TrafficService { - private readonly JT808AtomicCounter receiveCounter = new JT808AtomicCounter(); + public JT808TrafficService() + { + receiveCounter = new JT808AtomicCounter(); + sendCounter = new JT808AtomicCounter(); + } + + private readonly JT808AtomicCounter receiveCounter; - private readonly JT808AtomicCounter sendCounter = new JT808AtomicCounter(); + private readonly JT808AtomicCounter sendCounter; public void ReceiveSize(long size) { diff --git a/src/JT808.DotNetty.Core/Services/JT808TrafficServiceFactory.cs b/src/JT808.DotNetty.Core/Services/JT808TrafficServiceFactory.cs new file mode 100644 index 0000000..15b49e4 --- /dev/null +++ b/src/JT808.DotNetty.Core/Services/JT808TrafficServiceFactory.cs @@ -0,0 +1,33 @@ +using JT808.DotNetty.Core.Enums; +using JT808.DotNetty.Core.Metadata; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Text; + +namespace JT808.DotNetty.Core.Services +{ + public class JT808TrafficServiceFactory + { + private readonly ConcurrentDictionary cache; + + private JT808TrafficServiceFactory() + { + cache = new ConcurrentDictionary(); + } + + public JT808TrafficService Create(JT808ModeType type) + { + if (cache.TryGetValue(type, out var service)) + { + return service; + } + else + { + var serviceNew = new JT808TrafficService(); + cache.TryAdd(type, serviceNew); + return serviceNew; + } + } + } +} diff --git a/src/JT808.DotNetty.Core/Services/JT808UdpAtomicCounterService.cs b/src/JT808.DotNetty.Core/Services/JT808UdpAtomicCounterService.cs deleted file mode 100644 index 7c17fbf..0000000 --- a/src/JT808.DotNetty.Core/Services/JT808UdpAtomicCounterService.cs +++ /dev/null @@ -1,51 +0,0 @@ -using JT808.DotNetty.Core.Metadata; - -namespace JT808.DotNetty.Core.Services -{ - /// - /// Udp计数包服务 - /// - public class JT808UdpAtomicCounterService - { - private readonly JT808AtomicCounter MsgSuccessCounter = new JT808AtomicCounter(); - - private readonly JT808AtomicCounter MsgFailCounter = new JT808AtomicCounter(); - - public JT808UdpAtomicCounterService() - { - - } - - public void Reset() - { - MsgSuccessCounter.Reset(); - MsgFailCounter.Reset(); - } - - public long MsgSuccessIncrement() - { - return MsgSuccessCounter.Increment(); - } - - public long MsgSuccessCount - { - get - { - return MsgSuccessCounter.Count; - } - } - - public long MsgFailIncrement() - { - return MsgFailCounter.Increment(); - } - - public long MsgFailCount - { - get - { - return MsgFailCounter.Count; - } - } - } -} diff --git a/src/JT808.DotNetty.Core/Services/JT808UdpTrafficService.cs b/src/JT808.DotNetty.Core/Services/JT808UdpTrafficService.cs deleted file mode 100644 index 5c94b8e..0000000 --- a/src/JT808.DotNetty.Core/Services/JT808UdpTrafficService.cs +++ /dev/null @@ -1,40 +0,0 @@ -using JT808.DotNetty.Core.Metadata; -using System; -using System.Collections.Generic; -using System.Text; - -namespace JT808.DotNetty.Core.Services -{ - public class JT808UdpTrafficService - { - private readonly JT808AtomicCounter receiveCounter = new JT808AtomicCounter(); - - private readonly JT808AtomicCounter sendCounter = new JT808AtomicCounter(); - - public void ReceiveSize(long size) - { - receiveCounter.Add(size); - } - - public long TotalReceiveSize - { - get { return receiveCounter.Count; } - } - - public long TotalSendSize - { - get { return sendCounter.Count; } - } - - public void SendSize(long size) - { - sendCounter.Add(size); - } - - public void ResetSize() - { - receiveCounter.Reset(); - sendCounter.Reset(); - } - } -} diff --git a/src/JT808.DotNetty.Core/Services/JT808UnificationTcpSendService.cs b/src/JT808.DotNetty.Core/Services/JT808UnificationTcpSendService.cs index b762218..651bf35 100644 --- a/src/JT808.DotNetty.Core/Services/JT808UnificationTcpSendService.cs +++ b/src/JT808.DotNetty.Core/Services/JT808UnificationTcpSendService.cs @@ -12,13 +12,13 @@ namespace JT808.DotNetty.Internal { private readonly JT808TcpSessionManager jT808SessionManager; - private readonly JT808TcpTrafficService jT808TcpTrafficService; + private readonly JT808TrafficService jT808TrafficService; public JT808UnificationTcpSendService( - JT808TcpTrafficService jT808TcpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, JT808TcpSessionManager jT808SessionManager) { - this.jT808TcpTrafficService = jT808TcpTrafficService; + this.jT808TrafficService = jT808TrafficServiceFactory.Create(Core.Enums.JT808ModeType.Tcp); this.jT808SessionManager = jT808SessionManager; } @@ -39,7 +39,7 @@ namespace JT808.DotNetty.Internal } else { - jT808TcpTrafficService.SendSize(data.Length); + jT808TrafficService.SendSize(data.Length); session.Channel.WriteAndFlushAsync(Unpooled.WrappedBuffer(data)); resultDto.Code = JT808ResultCode.Ok; resultDto.Data = true; diff --git a/src/JT808.DotNetty.Core/Services/JT808UnificationUdpSendService.cs b/src/JT808.DotNetty.Core/Services/JT808UnificationUdpSendService.cs index 896e2ac..5a58f83 100644 --- a/src/JT808.DotNetty.Core/Services/JT808UnificationUdpSendService.cs +++ b/src/JT808.DotNetty.Core/Services/JT808UnificationUdpSendService.cs @@ -12,13 +12,13 @@ namespace JT808.DotNetty.Internal { private readonly JT808UdpSessionManager jT808SessionManager; - private readonly JT808UdpTrafficService jT808UdpTrafficService; + private readonly JT808TrafficService jT808TrafficService; public JT808UnificationUdpSendService( - JT808UdpTrafficService jT808UdpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, JT808UdpSessionManager jT808SessionManager) { - this.jT808UdpTrafficService = jT808UdpTrafficService; + this.jT808TrafficService = jT808TrafficServiceFactory.Create(Core.Enums.JT808ModeType.Udp); this.jT808SessionManager = jT808SessionManager; } @@ -30,7 +30,7 @@ namespace JT808.DotNetty.Internal var session = jT808SessionManager.GetSession(terminalPhoneNo); if (session != null) { - jT808UdpTrafficService.SendSize(data.Length); + jT808TrafficService.SendSize(data.Length); session.Channel.WriteAndFlushAsync(new DatagramPacket(Unpooled.WrappedBuffer(data), session.Sender)); resultDto.Code = JT808ResultCode.Ok; resultDto.Data = true; diff --git a/src/JT808.DotNetty.Tcp/Handlers/JT808TcpServerHandler.cs b/src/JT808.DotNetty.Tcp/Handlers/JT808TcpServerHandler.cs index 083c68c..429f152 100644 --- a/src/JT808.DotNetty.Tcp/Handlers/JT808TcpServerHandler.cs +++ b/src/JT808.DotNetty.Tcp/Handlers/JT808TcpServerHandler.cs @@ -24,27 +24,27 @@ namespace JT808.DotNetty.Tcp.Handlers private readonly IJT808SourcePackageDispatcher jT808SourcePackageDispatcher; - private readonly JT808TcpAtomicCounterService jT808AtomicCounterService; + private readonly JT808AtomicCounterService jT808AtomicCounterService; - private readonly JT808TcpTrafficService jT808TcpTrafficService; + private readonly JT808TrafficService jT808TrafficService; private readonly ILogger logger; public JT808TcpServerHandler( - JT808TcpTrafficService jT808TcpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, ILoggerFactory loggerFactory, JT808TransmitAddressFilterService jT808TransmitAddressFilterService, IJT808SourcePackageDispatcher jT808SourcePackageDispatcher, JT808MsgIdTcpHandlerBase handler, - JT808TcpAtomicCounterService jT808AtomicCounterService, + JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory, JT808TcpSessionManager jT808SessionManager) { - this.jT808TcpTrafficService = jT808TcpTrafficService; + this.jT808TrafficService = jT808TrafficServiceFactory.Create(Core.Enums.JT808ModeType.Tcp); this.jT808TransmitAddressFilterService = jT808TransmitAddressFilterService; this.handler = handler; this.jT808SessionManager = jT808SessionManager; this.jT808SourcePackageDispatcher = jT808SourcePackageDispatcher; - this.jT808AtomicCounterService = jT808AtomicCounterService; + this.jT808AtomicCounterService = jT808AtomicCounterServiceFactory.Create(Core.Enums.JT808ModeType.Tcp); logger = loggerFactory.CreateLogger(); } @@ -59,7 +59,7 @@ namespace JT808.DotNetty.Tcp.Handlers //解析具体的消息体,具体调用JT808Serializer.Deserialize JT808HeaderPackage jT808HeaderPackage = JT808Serializer.Deserialize(msg); jT808AtomicCounterService.MsgSuccessIncrement(); - jT808TcpTrafficService.ReceiveSize(msg.Length); + jT808TrafficService.ReceiveSize(msg.Length); if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug("accept package success count<<<" + jT808AtomicCounterService.MsgSuccessCount.ToString()); @@ -74,7 +74,7 @@ namespace JT808.DotNetty.Tcp.Handlers if (!jT808TransmitAddressFilterService.ContainsKey(ctx.Channel.RemoteAddress)) { var sendData = JT808Serializer.Serialize(jT808Response.Package, jT808Response.MinBufferSize); - jT808TcpTrafficService.SendSize(sendData.Length); + jT808TrafficService.SendSize(sendData.Length); ctx.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendData)); } } diff --git a/src/JT808.DotNetty.Tcp/JT808TcpDotnettyExtensions.cs b/src/JT808.DotNetty.Tcp/JT808TcpDotnettyExtensions.cs index 5bc1c72..577de2c 100644 --- a/src/JT808.DotNetty.Tcp/JT808TcpDotnettyExtensions.cs +++ b/src/JT808.DotNetty.Tcp/JT808TcpDotnettyExtensions.cs @@ -21,9 +21,7 @@ namespace JT808.DotNetty.Tcp public static IServiceCollection AddJT808TcpHost(this IServiceCollection serviceDescriptors) { serviceDescriptors.TryAddSingleton(); - serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddSingleton(); - serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddScoped(); serviceDescriptors.TryAddScoped(); diff --git a/src/JT808.DotNetty.Udp/Handlers/JT808UdpServerHandler.cs b/src/JT808.DotNetty.Udp/Handlers/JT808UdpServerHandler.cs index 5059305..127ab33 100644 --- a/src/JT808.DotNetty.Udp/Handlers/JT808UdpServerHandler.cs +++ b/src/JT808.DotNetty.Udp/Handlers/JT808UdpServerHandler.cs @@ -20,7 +20,7 @@ namespace JT808.DotNetty.Udp.Handlers { private readonly IJT808SourcePackageDispatcher jT808SourcePackageDispatcher; - private readonly JT808UdpAtomicCounterService jT808UdpAtomicCounterService; + private readonly JT808AtomicCounterService jT808AtomicCounterService; private readonly ILogger logger; @@ -28,20 +28,20 @@ namespace JT808.DotNetty.Udp.Handlers private readonly JT808MsgIdUdpHandlerBase handler; - private readonly JT808UdpTrafficService jT808UdpTrafficService; + private readonly JT808TrafficService jT808TrafficService; public JT808UdpServerHandler( - JT808UdpTrafficService jT808UdpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, ILoggerFactory loggerFactory, IJT808SourcePackageDispatcher jT808SourcePackageDispatcher, JT808MsgIdUdpHandlerBase handler, - JT808UdpAtomicCounterService jT808UdpAtomicCounterService, + JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory, JT808UdpSessionManager jT808UdpSessionManager) { - this.jT808UdpTrafficService = jT808UdpTrafficService; + this.jT808TrafficService = jT808TrafficServiceFactory.Create(Core.Enums.JT808ModeType.Udp); this.handler = handler; this.jT808SourcePackageDispatcher = jT808SourcePackageDispatcher; - this.jT808UdpAtomicCounterService = jT808UdpAtomicCounterService; + this.jT808AtomicCounterService = jT808AtomicCounterServiceFactory.Create(Core.Enums.JT808ModeType.Udp); this.jT808UdpSessionManager = jT808UdpSessionManager; logger = loggerFactory.CreateLogger(); } @@ -51,16 +51,16 @@ namespace JT808.DotNetty.Udp.Handlers try { jT808SourcePackageDispatcher?.SendAsync(msg.Buffer); - jT808UdpTrafficService.ReceiveSize(msg.Buffer.Length); + jT808TrafficService.ReceiveSize(msg.Buffer.Length); //解析到头部,然后根据具体的消息Id通过队列去进行消费 //要是一定要解析到数据体可以在JT808MsgIdHandlerBase类中根据具体的消息, //解析具体的消息体,具体调用JT808Serializer.Deserialize JT808HeaderPackage jT808HeaderPackage = JT808Serializer.Deserialize(msg.Buffer); - jT808UdpAtomicCounterService.MsgSuccessIncrement(); + jT808AtomicCounterService.MsgSuccessIncrement(); jT808UdpSessionManager.TryAdd(ctx.Channel, msg.Sender, jT808HeaderPackage.Header.TerminalPhoneNo); if (logger.IsEnabled(LogLevel.Debug)) { - logger.LogDebug("accept package success count<<<" + jT808UdpAtomicCounterService.MsgSuccessCount.ToString()); + logger.LogDebug("accept package success count<<<" + jT808AtomicCounterService.MsgSuccessCount.ToString()); } Func handlerFunc; if (handler.HandlerDict.TryGetValue(jT808HeaderPackage.Header.MsgId, out handlerFunc)) @@ -69,26 +69,26 @@ namespace JT808.DotNetty.Udp.Handlers if (jT808Response != null) { var sendData = JT808Serializer.Serialize(jT808Response.Package, jT808Response.MinBufferSize); - jT808UdpTrafficService.SendSize(sendData.Length); + jT808TrafficService.SendSize(sendData.Length); ctx.WriteAndFlushAsync(new DatagramPacket(Unpooled.WrappedBuffer(sendData), msg.Sender)); } } } catch (JT808.Protocol.Exceptions.JT808Exception ex) { - jT808UdpAtomicCounterService.MsgFailIncrement(); + jT808AtomicCounterService.MsgFailIncrement(); if (logger.IsEnabled(LogLevel.Error)) { - logger.LogError("accept package fail count<<<" + jT808UdpAtomicCounterService.MsgFailCount.ToString()); + logger.LogError("accept package fail count<<<" + jT808AtomicCounterService.MsgFailCount.ToString()); logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg.Buffer)); } } catch (Exception ex) { - jT808UdpAtomicCounterService.MsgFailIncrement(); + jT808AtomicCounterService.MsgFailIncrement(); if (logger.IsEnabled(LogLevel.Error)) { - logger.LogError("accept package fail count<<<" + jT808UdpAtomicCounterService.MsgFailCount.ToString()); + logger.LogError("accept package fail count<<<" + jT808AtomicCounterService.MsgFailCount.ToString()); logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg.Buffer)); } } diff --git a/src/JT808.DotNetty.Udp/JT808UdpDotnettyExtensions.cs b/src/JT808.DotNetty.Udp/JT808UdpDotnettyExtensions.cs index 6e21558..9081927 100644 --- a/src/JT808.DotNetty.Udp/JT808UdpDotnettyExtensions.cs +++ b/src/JT808.DotNetty.Udp/JT808UdpDotnettyExtensions.cs @@ -19,8 +19,6 @@ namespace JT808.DotNetty.Udp public static IServiceCollection AddJT808UdpHost(this IServiceCollection serviceDescriptors) { serviceDescriptors.TryAddSingleton(); - serviceDescriptors.TryAddSingleton(); - serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddSingleton(); serviceDescriptors.TryAddScoped(); serviceDescriptors.TryAddScoped(); diff --git a/src/JT808.DotNetty.WebApi/Handlers/JT808MsgIdDefaultWebApiHandler.cs b/src/JT808.DotNetty.WebApi/Handlers/JT808MsgIdDefaultWebApiHandler.cs index 2d741c9..d7f86e9 100644 --- a/src/JT808.DotNetty.WebApi/Handlers/JT808MsgIdDefaultWebApiHandler.cs +++ b/src/JT808.DotNetty.WebApi/Handlers/JT808MsgIdDefaultWebApiHandler.cs @@ -1,5 +1,6 @@ using JT808.DotNetty.Abstractions; using JT808.DotNetty.Abstractions.Dtos; +using JT808.DotNetty.Core.Enums; using JT808.DotNetty.Core.Handlers; using JT808.DotNetty.Core.Interfaces; using JT808.DotNetty.Core.Metadata; @@ -13,9 +14,9 @@ namespace JT808.DotNetty.WebApi.Handlers /// public class JT808MsgIdDefaultWebApiHandler : JT808MsgIdHttpHandlerBase { - private readonly JT808TcpAtomicCounterService jT808TcpAtomicCounterService; + private readonly JT808AtomicCounterService jT808TcpAtomicCounterService; - private readonly JT808UdpAtomicCounterService jT808UdpAtomicCounterService; + private readonly JT808AtomicCounterService jT808UdpAtomicCounterService; private readonly JT808TransmitAddressFilterService jT808TransmitAddressFilterService; @@ -27,9 +28,9 @@ namespace JT808.DotNetty.WebApi.Handlers private readonly IJT808UnificationUdpSendService jT808UnificationUdpSendService; - private readonly JT808TcpTrafficService jT808TcpTrafficService; + private readonly JT808TrafficService jT808TcpTrafficService; - private readonly JT808UdpTrafficService jT808UdpTrafficService; + private readonly JT808TrafficService jT808UdpTrafficService; private readonly JT808SimpleSystemCollectService jT808SimpleSystemCollectService; @@ -39,19 +40,19 @@ namespace JT808.DotNetty.WebApi.Handlers /// public JT808MsgIdDefaultWebApiHandler( JT808SimpleSystemCollectService jT808SimpleSystemCollectService, - JT808TcpTrafficService jT808TcpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, IJT808UnificationTcpSendService jT808UnificationTcpSendService, IJT808TcpSessionService jT808TcpSessionService, JT808TransmitAddressFilterService jT808TransmitAddressFilterService, - JT808TcpAtomicCounterService jT808TcpAtomicCounterService + JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory ) { this.jT808SimpleSystemCollectService = jT808SimpleSystemCollectService; - this.jT808TcpTrafficService = jT808TcpTrafficService; + this.jT808TcpTrafficService = jT808TrafficServiceFactory.Create(JT808ModeType.Tcp); this.jT808UnificationTcpSendService = jT808UnificationTcpSendService; this.jT808TcpSessionService = jT808TcpSessionService; this.jT808TransmitAddressFilterService = jT808TransmitAddressFilterService; - this.jT808TcpAtomicCounterService = jT808TcpAtomicCounterService; + this.jT808TcpAtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808ModeType.Tcp); InitCommonRoute(); InitTcpRoute(); } @@ -62,17 +63,17 @@ namespace JT808.DotNetty.WebApi.Handlers /// public JT808MsgIdDefaultWebApiHandler( JT808SimpleSystemCollectService jT808SimpleSystemCollectService, - JT808UdpTrafficService jT808UdpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, IJT808UdpSessionService jT808UdpSessionService, IJT808UnificationUdpSendService jT808UnificationUdpSendService, - JT808UdpAtomicCounterService jT808UdpAtomicCounterService + JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory ) { this.jT808SimpleSystemCollectService = jT808SimpleSystemCollectService; - this.jT808UdpTrafficService = jT808UdpTrafficService; + this.jT808UdpTrafficService = jT808TrafficServiceFactory.Create(JT808ModeType.Udp); this.jT808UdpSessionService = jT808UdpSessionService; this.jT808UnificationUdpSendService = jT808UnificationUdpSendService; - this.jT808UdpAtomicCounterService = jT808UdpAtomicCounterService; + this.jT808UdpAtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808ModeType.Udp); InitCommonRoute(); InitUdpRoute(); } @@ -84,27 +85,25 @@ namespace JT808.DotNetty.WebApi.Handlers /// public JT808MsgIdDefaultWebApiHandler( JT808SimpleSystemCollectService jT808SimpleSystemCollectService, - JT808TcpTrafficService jT808TcpTrafficService, - JT808UdpTrafficService jT808UdpTrafficService, + JT808TrafficServiceFactory jT808TrafficServiceFactory, IJT808UnificationTcpSendService jT808UnificationTcpSendService, IJT808UnificationUdpSendService jT808UnificationUdpSendService, IJT808TcpSessionService jT808TcpSessionService, IJT808UdpSessionService jT808UdpSessionService, JT808TransmitAddressFilterService jT808TransmitAddressFilterService, - JT808TcpAtomicCounterService jT808TcpAtomicCounterService, - JT808UdpAtomicCounterService jT808UdpAtomicCounterService + JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory ) { this.jT808SimpleSystemCollectService = jT808SimpleSystemCollectService; - this.jT808TcpTrafficService = jT808TcpTrafficService; - this.jT808UdpTrafficService = jT808UdpTrafficService; + this.jT808TcpTrafficService = jT808TrafficServiceFactory.Create(JT808ModeType.Tcp); + this.jT808UdpTrafficService = jT808TrafficServiceFactory.Create(JT808ModeType.Udp); this.jT808UdpSessionService = jT808UdpSessionService; this.jT808UnificationTcpSendService = jT808UnificationTcpSendService; this.jT808UnificationUdpSendService = jT808UnificationUdpSendService; this.jT808TcpSessionService = jT808TcpSessionService; this.jT808TransmitAddressFilterService = jT808TransmitAddressFilterService; - this.jT808TcpAtomicCounterService = jT808TcpAtomicCounterService; - this.jT808UdpAtomicCounterService = jT808UdpAtomicCounterService; + this.jT808TcpAtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808ModeType.Tcp); + this.jT808UdpAtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808ModeType.Udp); InitCommonRoute(); InitTcpRoute(); InitUdpRoute(); diff --git a/src/JT808.DotNetty.WebApiClientTool/JT808.DotNetty.WebApiClientTool.csproj b/src/JT808.DotNetty.WebApiClientTool/JT808.DotNetty.WebApiClientTool.csproj index 51eb294..75d438e 100644 --- a/src/JT808.DotNetty.WebApiClientTool/JT808.DotNetty.WebApiClientTool.csproj +++ b/src/JT808.DotNetty.WebApiClientTool/JT808.DotNetty.WebApiClientTool.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/JT808.DotNetty.sln b/src/JT808.DotNetty.sln index c48c449..b31d8b3 100644 --- a/src/JT808.DotNetty.sln +++ b/src/JT808.DotNetty.sln @@ -31,6 +31,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.DotNetty.Hosting", "J EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.DotNetty.WebApiClientTool", "JT808.DotNetty.WebApiClientTool\JT808.DotNetty.WebApiClientTool.csproj", "{9D86C951-94F2-4CBD-B177-8AF31DDB05D8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.DotNetty.Client", "JT808.DotNetty.Client\JT808.DotNetty.Client.csproj", "{87C08239-C57F-4FC5-9579-05D0723AA4A0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -85,6 +87,10 @@ Global {9D86C951-94F2-4CBD-B177-8AF31DDB05D8}.Debug|Any CPU.Build.0 = Debug|Any CPU {9D86C951-94F2-4CBD-B177-8AF31DDB05D8}.Release|Any CPU.ActiveCfg = Release|Any CPU {9D86C951-94F2-4CBD-B177-8AF31DDB05D8}.Release|Any CPU.Build.0 = Release|Any CPU + {87C08239-C57F-4FC5-9579-05D0723AA4A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87C08239-C57F-4FC5-9579-05D0723AA4A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87C08239-C57F-4FC5-9579-05D0723AA4A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87C08239-C57F-4FC5-9579-05D0723AA4A0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE