From 0d68665ab220a028abd46eefd30fa82c6909ec41 Mon Sep 17 00:00:00 2001
From: "SmallChi(Koike)" <564952747@qq.com>
Date: Sun, 1 Sep 2019 22:10:32 +0800
Subject: [PATCH] =?UTF-8?q?1.=E8=BF=98=E6=98=AF=E9=80=9A=E8=BF=87=E7=BD=91?=
=?UTF-8?q?=E5=85=B3=E9=AA=8C=E8=AF=81=E6=A3=80=E9=AA=8C=E5=92=8C=202.?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0808=E6=B6=88=E6=81=AF=E7=9A=84=E7=94=9F?=
=?UTF-8?q?=E4=BA=A7=E6=B6=88=E8=B4=B9=E5=8F=8A=E6=B5=8B=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../JT808.DotNetty.Kafka.csproj | 11 ++-
.../JT808ConsumerConfig.cs | 15 ++++
src/JT808.DotNetty.Kafka/JT808MsgConsumer.cs | 83 +++++++++++++++++++
src/JT808.DotNetty.Kafka/JT808MsgProducer.cs | 38 +++++++++
.../JT808MsgReplyConsumer.cs | 83 +++++++++++++++++++
.../JT808MsgReplyProducer.cs | 38 +++++++++
.../JT808ProducerConfig.cs | 15 ++++
.../JT808.DotNetty.RabbitMQ.csproj | 11 +++
.../JT808MsgProducer.cs | 35 ++++++++
.../JT808ProducerConfig.cs | 14 ++++
.../Handlers/JT808TcpServerHandler.cs | 1 -
.../JT808.DotNetty.Kafka.Test.csproj | 21 +++++
.../JT808MsgProducerTest.cs | 20 +++++
.../JT808.DotNetty.RabbitMQ.Test.csproj | 15 ++++
.../JT808.DotNetty.RabbitMQ.Test/UnitTest1.cs | 14 ++++
.../Handlers/JT808UdpServerHandler.cs | 1 -
src/JT808.DotNetty.sln | 34 +++++---
17 files changed, 435 insertions(+), 14 deletions(-)
create mode 100644 src/JT808.DotNetty.Kafka/JT808ConsumerConfig.cs
create mode 100644 src/JT808.DotNetty.Kafka/JT808MsgConsumer.cs
create mode 100644 src/JT808.DotNetty.Kafka/JT808MsgProducer.cs
create mode 100644 src/JT808.DotNetty.Kafka/JT808MsgReplyConsumer.cs
create mode 100644 src/JT808.DotNetty.Kafka/JT808MsgReplyProducer.cs
create mode 100644 src/JT808.DotNetty.Kafka/JT808ProducerConfig.cs
create mode 100644 src/JT808.DotNetty.RabbitMQ/JT808MsgProducer.cs
create mode 100644 src/JT808.DotNetty.RabbitMQ/JT808ProducerConfig.cs
create mode 100644 src/JT808.DotNetty.Tests/JT808.DotNetty.Kafka.Test/JT808.DotNetty.Kafka.Test.csproj
create mode 100644 src/JT808.DotNetty.Tests/JT808.DotNetty.Kafka.Test/JT808MsgProducerTest.cs
create mode 100644 src/JT808.DotNetty.Tests/JT808.DotNetty.RabbitMQ.Test/JT808.DotNetty.RabbitMQ.Test.csproj
create mode 100644 src/JT808.DotNetty.Tests/JT808.DotNetty.RabbitMQ.Test/UnitTest1.cs
diff --git a/src/JT808.DotNetty.Kafka/JT808.DotNetty.Kafka.csproj b/src/JT808.DotNetty.Kafka/JT808.DotNetty.Kafka.csproj
index 73dd61a..3eb35c4 100644
--- a/src/JT808.DotNetty.Kafka/JT808.DotNetty.Kafka.csproj
+++ b/src/JT808.DotNetty.Kafka/JT808.DotNetty.Kafka.csproj
@@ -1,4 +1,4 @@
-
+
JT808.DotNetty.Kafka
@@ -6,5 +6,12 @@
基于Kafka的JT808消息发布与订阅
基于Kafka的JT808消息发布与订阅
-
+
+
+
+
+
+
+
+
diff --git a/src/JT808.DotNetty.Kafka/JT808ConsumerConfig.cs b/src/JT808.DotNetty.Kafka/JT808ConsumerConfig.cs
new file mode 100644
index 0000000..5ff137a
--- /dev/null
+++ b/src/JT808.DotNetty.Kafka/JT808ConsumerConfig.cs
@@ -0,0 +1,15 @@
+using Confluent.Kafka;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT808.DotNetty.Kafka
+{
+ public class JT808ConsumerConfig: ConsumerConfig, IOptions
+ {
+ public string TopicName { get; set; }
+
+ public JT808ConsumerConfig Value => this;
+ }
+}
diff --git a/src/JT808.DotNetty.Kafka/JT808MsgConsumer.cs b/src/JT808.DotNetty.Kafka/JT808MsgConsumer.cs
new file mode 100644
index 0000000..76d84c2
--- /dev/null
+++ b/src/JT808.DotNetty.Kafka/JT808MsgConsumer.cs
@@ -0,0 +1,83 @@
+using Confluent.Kafka;
+using JT808.DotNetty.Abstractions;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace JT808.DotNetty.Kafka
+{
+ public class JT808MsgConsumer : IJT808MsgConsumer
+ {
+ public CancellationTokenSource Cts => new CancellationTokenSource();
+
+ private readonly IConsumer consumer;
+
+ private readonly ILogger logger;
+
+ public string TopicName { get; }
+
+ public JT808MsgConsumer(
+ IOptions consumerConfigAccessor,
+ ILoggerFactory loggerFactory)
+ {
+ consumer = new ConsumerBuilder(consumerConfigAccessor.Value).Build();
+ logger = loggerFactory.CreateLogger("JT808MsgConsumer");
+ }
+
+ public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback)
+ {
+ Task.Run(() =>
+ {
+ while (!Cts.IsCancellationRequested)
+ {
+ try
+ {
+ //如果不指定分区,根据kafka的机制会从多个分区中拉取数据
+ //如果指定分区,根据kafka的机制会从相应的分区中拉取数据
+ var data = consumer.Consume(Cts.Token);
+ if (logger.IsEnabled(LogLevel.Debug))
+ {
+ logger.LogDebug($"Topic: {data.Topic} Key: {data.Key} Partition: {data.Partition} Offset: {data.Offset} TopicPartitionOffset:{data.TopicPartitionOffset}");
+ }
+ callback((data.Key, data.Value));
+ }
+ catch (ConsumeException ex)
+ {
+ logger.LogError(ex, TopicName);
+ Thread.Sleep(1000);
+ }
+ catch (OperationCanceledException ex)
+ {
+ logger.LogError(ex, TopicName);
+ Thread.Sleep(1000);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, TopicName);
+ Thread.Sleep(1000);
+ }
+ }
+ }, Cts.Token);
+ }
+
+ public void Subscribe()
+ {
+ consumer.Subscribe(TopicName);
+ }
+
+ public void Unsubscribe()
+ {
+ consumer.Unsubscribe();
+ }
+
+ public void Dispose()
+ {
+ consumer.Close();
+ consumer.Dispose();
+ }
+ }
+}
diff --git a/src/JT808.DotNetty.Kafka/JT808MsgProducer.cs b/src/JT808.DotNetty.Kafka/JT808MsgProducer.cs
new file mode 100644
index 0000000..cae0138
--- /dev/null
+++ b/src/JT808.DotNetty.Kafka/JT808MsgProducer.cs
@@ -0,0 +1,38 @@
+using Confluent.Kafka;
+using JT808.DotNetty.Abstractions;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace JT808.DotNetty.Kafka
+{
+ public class JT808MsgProducer : IJT808MsgProducer
+ {
+ public string TopicName { get; }
+
+ private readonly IProducer producer;
+ public JT808MsgProducer(
+ IOptions producerConfigAccessor)
+ {
+ producer = new ProducerBuilder(producerConfigAccessor.Value).Build();
+ TopicName = producerConfigAccessor.Value.TopicName;
+ }
+
+ public void Dispose()
+ {
+ producer.Dispose();
+ }
+
+ public Task ProduceAsync(string terminalNo, byte[] data)
+ {
+ producer.ProduceAsync(TopicName, new Message
+ {
+ Key = terminalNo,
+ Value = data
+ });
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/src/JT808.DotNetty.Kafka/JT808MsgReplyConsumer.cs b/src/JT808.DotNetty.Kafka/JT808MsgReplyConsumer.cs
new file mode 100644
index 0000000..3903af7
--- /dev/null
+++ b/src/JT808.DotNetty.Kafka/JT808MsgReplyConsumer.cs
@@ -0,0 +1,83 @@
+using Confluent.Kafka;
+using JT808.DotNetty.Abstractions;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace JT808.DotNetty.Kafka
+{
+ public class JT808MsgReplyConsumer : IJT808MsgConsumer
+ {
+ public CancellationTokenSource Cts => new CancellationTokenSource();
+
+ private readonly IConsumer consumer;
+
+ private readonly ILogger logger;
+
+ public string TopicName { get; }
+
+ public JT808MsgReplyConsumer(
+ IOptions consumerConfigAccessor,
+ ILoggerFactory loggerFactory)
+ {
+ consumer = new ConsumerBuilder(consumerConfigAccessor.Value).Build();
+ logger = loggerFactory.CreateLogger("JT808MsgReplyConsumer");
+ }
+
+ public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback)
+ {
+ Task.Run(() =>
+ {
+ while (!Cts.IsCancellationRequested)
+ {
+ try
+ {
+ //如果不指定分区,根据kafka的机制会从多个分区中拉取数据
+ //如果指定分区,根据kafka的机制会从相应的分区中拉取数据
+ var data = consumer.Consume(Cts.Token);
+ if (logger.IsEnabled(LogLevel.Debug))
+ {
+ logger.LogDebug($"Topic: {data.Topic} Key: {data.Key} Partition: {data.Partition} Offset: {data.Offset} TopicPartitionOffset:{data.TopicPartitionOffset}");
+ }
+ callback((data.Key, data.Value));
+ }
+ catch (ConsumeException ex)
+ {
+ logger.LogError(ex, TopicName);
+ Thread.Sleep(1000);
+ }
+ catch (OperationCanceledException ex)
+ {
+ logger.LogError(ex, TopicName);
+ Thread.Sleep(1000);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, TopicName);
+ Thread.Sleep(1000);
+ }
+ }
+ }, Cts.Token);
+ }
+
+ public void Subscribe()
+ {
+ consumer.Subscribe(TopicName);
+ }
+
+ public void Unsubscribe()
+ {
+ consumer.Unsubscribe();
+ }
+
+ public void Dispose()
+ {
+ consumer.Close();
+ consumer.Dispose();
+ }
+ }
+}
diff --git a/src/JT808.DotNetty.Kafka/JT808MsgReplyProducer.cs b/src/JT808.DotNetty.Kafka/JT808MsgReplyProducer.cs
new file mode 100644
index 0000000..bc49e93
--- /dev/null
+++ b/src/JT808.DotNetty.Kafka/JT808MsgReplyProducer.cs
@@ -0,0 +1,38 @@
+using Confluent.Kafka;
+using JT808.DotNetty.Abstractions;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace JT808.DotNetty.Kafka
+{
+ public class JT808MsgReplyProducer : IJT808MsgProducer
+ {
+ public string TopicName { get;}
+
+ private IProducer producer;
+ public JT808MsgReplyProducer(
+ IOptions producerConfigAccessor)
+ {
+ producer = new ProducerBuilder(producerConfigAccessor.Value).Build();
+ TopicName = producerConfigAccessor.Value.TopicName;
+ }
+
+ public void Dispose()
+ {
+ producer.Dispose();
+ }
+
+ public Task ProduceAsync(string terminalNo, byte[] data)
+ {
+ producer.ProduceAsync(TopicName, new Message
+ {
+ Key = terminalNo,
+ Value = data
+ });
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/src/JT808.DotNetty.Kafka/JT808ProducerConfig.cs b/src/JT808.DotNetty.Kafka/JT808ProducerConfig.cs
new file mode 100644
index 0000000..1a3c9ad
--- /dev/null
+++ b/src/JT808.DotNetty.Kafka/JT808ProducerConfig.cs
@@ -0,0 +1,15 @@
+using Confluent.Kafka;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT808.DotNetty.Kafka
+{
+ public class JT808ProducerConfig : ProducerConfig,IOptions
+ {
+ public string TopicName { get; set; }
+
+ public JT808ProducerConfig Value => this;
+ }
+}
diff --git a/src/JT808.DotNetty.RabbitMQ/JT808.DotNetty.RabbitMQ.csproj b/src/JT808.DotNetty.RabbitMQ/JT808.DotNetty.RabbitMQ.csproj
index 8e980a9..0f3fc58 100644
--- a/src/JT808.DotNetty.RabbitMQ/JT808.DotNetty.RabbitMQ.csproj
+++ b/src/JT808.DotNetty.RabbitMQ/JT808.DotNetty.RabbitMQ.csproj
@@ -7,5 +7,16 @@
基于RabbitMQ的JT808消息发布与订阅
基于RabbitMQ的JT808消息发布与订阅
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/JT808.DotNetty.RabbitMQ/JT808MsgProducer.cs b/src/JT808.DotNetty.RabbitMQ/JT808MsgProducer.cs
new file mode 100644
index 0000000..4f0b149
--- /dev/null
+++ b/src/JT808.DotNetty.RabbitMQ/JT808MsgProducer.cs
@@ -0,0 +1,35 @@
+using EasyNetQ;
+using EasyNetQ.Topology;
+using JT808.DotNetty.Abstractions;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace JT808.DotNetty.RabbitMQ
+{
+ public class JT808MsgProducer : IJT808MsgProducer
+ {
+ public string TopicName { get; }
+
+ private readonly IBus bus;
+ public JT808MsgProducer(IOptions producerConfigAccessor)
+ {
+ bus = RabbitHutch.CreateBus(producerConfigAccessor.Value.ConnectionString);
+ TopicName = producerConfigAccessor.Value.TopicName;
+ }
+
+ public void Dispose()
+ {
+ bus.Dispose();
+ }
+
+ public Task ProduceAsync(string terminalNo, byte[] data)
+ {
+ var exchange = bus.Advanced.ExchangeDeclare(TopicName, ExchangeType.Fanout);
+ bus.Advanced.Publish(exchange, "", false, new Message(data));
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/src/JT808.DotNetty.RabbitMQ/JT808ProducerConfig.cs b/src/JT808.DotNetty.RabbitMQ/JT808ProducerConfig.cs
new file mode 100644
index 0000000..cf43fa1
--- /dev/null
+++ b/src/JT808.DotNetty.RabbitMQ/JT808ProducerConfig.cs
@@ -0,0 +1,14 @@
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT808.DotNetty.RabbitMQ
+{
+ public class JT808ProducerConfig : IOptions
+ {
+ public string TopicName { get; set; }
+ public string ConnectionString { get; set; }
+ public JT808ProducerConfig Value => this;
+ }
+}
diff --git a/src/JT808.DotNetty.Tcp/Handlers/JT808TcpServerHandler.cs b/src/JT808.DotNetty.Tcp/Handlers/JT808TcpServerHandler.cs
index 1666b43..c65a5cf 100644
--- a/src/JT808.DotNetty.Tcp/Handlers/JT808TcpServerHandler.cs
+++ b/src/JT808.DotNetty.Tcp/Handlers/JT808TcpServerHandler.cs
@@ -37,7 +37,6 @@ namespace JT808.DotNetty.Tcp.Handlers
this.JT808MsgProducer = jT808MsgProducer;
this.jT808AtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808TransportProtocolType.tcp);
this.JT808Serializer = jT808Config.GetSerializer();
- jT808Config.SkipCRCCode = true;
logger = loggerFactory.CreateLogger();
}
diff --git a/src/JT808.DotNetty.Tests/JT808.DotNetty.Kafka.Test/JT808.DotNetty.Kafka.Test.csproj b/src/JT808.DotNetty.Tests/JT808.DotNetty.Kafka.Test/JT808.DotNetty.Kafka.Test.csproj
new file mode 100644
index 0000000..db1c6cf
--- /dev/null
+++ b/src/JT808.DotNetty.Tests/JT808.DotNetty.Kafka.Test/JT808.DotNetty.Kafka.Test.csproj
@@ -0,0 +1,21 @@
+
+
+
+ netcoreapp2.2
+
+ false
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
diff --git a/src/JT808.DotNetty.Tests/JT808.DotNetty.Kafka.Test/JT808MsgProducerTest.cs b/src/JT808.DotNetty.Tests/JT808.DotNetty.Kafka.Test/JT808MsgProducerTest.cs
new file mode 100644
index 0000000..bb8d49f
--- /dev/null
+++ b/src/JT808.DotNetty.Tests/JT808.DotNetty.Kafka.Test/JT808MsgProducerTest.cs
@@ -0,0 +1,20 @@
+using JT808.DotNetty.Abstractions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xunit;
+
+namespace JT808.DotNetty.Kafka.Test
+{
+ public class JT808MsgProducerTest
+ {
+ [Fact]
+ public void Test1()
+ {
+ using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808ProducerConfig { BootstrapServers = "192.168.3.11:9092" }))
+ {
+ jT808MsgProducer.ProduceAsync("123456", new byte[] { 0x7E, 0, 0x7E });
+ }
+ }
+ }
+}
diff --git a/src/JT808.DotNetty.Tests/JT808.DotNetty.RabbitMQ.Test/JT808.DotNetty.RabbitMQ.Test.csproj b/src/JT808.DotNetty.Tests/JT808.DotNetty.RabbitMQ.Test/JT808.DotNetty.RabbitMQ.Test.csproj
new file mode 100644
index 0000000..d45c579
--- /dev/null
+++ b/src/JT808.DotNetty.Tests/JT808.DotNetty.RabbitMQ.Test/JT808.DotNetty.RabbitMQ.Test.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netcoreapp2.2
+
+ false
+
+
+
+
+
+
+
+
+
diff --git a/src/JT808.DotNetty.Tests/JT808.DotNetty.RabbitMQ.Test/UnitTest1.cs b/src/JT808.DotNetty.Tests/JT808.DotNetty.RabbitMQ.Test/UnitTest1.cs
new file mode 100644
index 0000000..fc2ac69
--- /dev/null
+++ b/src/JT808.DotNetty.Tests/JT808.DotNetty.RabbitMQ.Test/UnitTest1.cs
@@ -0,0 +1,14 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace JT808.DotNetty.RabbitMQ.Test
+{
+ [TestClass]
+ public class UnitTest1
+ {
+ //https://www.rabbitmq.com/getstarted.html
+ [TestMethod]
+ public void TestMethod1()
+ {
+ }
+ }
+}
diff --git a/src/JT808.DotNetty.Udp/Handlers/JT808UdpServerHandler.cs b/src/JT808.DotNetty.Udp/Handlers/JT808UdpServerHandler.cs
index 1a0a023..e3c6471 100644
--- a/src/JT808.DotNetty.Udp/Handlers/JT808UdpServerHandler.cs
+++ b/src/JT808.DotNetty.Udp/Handlers/JT808UdpServerHandler.cs
@@ -38,7 +38,6 @@ namespace JT808.DotNetty.Udp.Handlers
this.jT808UdpSessionManager = jT808UdpSessionManager;
logger = loggerFactory.CreateLogger();
JT808Serializer = jT808Config.GetSerializer();
- jT808Config.SkipCRCCode = true;
}
protected override void ChannelRead0(IChannelHandlerContext ctx, JT808UdpPackage msg)
diff --git a/src/JT808.DotNetty.sln b/src/JT808.DotNetty.sln
index 51842ff..7d3576f 100644
--- a/src/JT808.DotNetty.sln
+++ b/src/JT808.DotNetty.sln
@@ -37,9 +37,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.DotNetty.SimpleServer
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.DotNetty.CleintBenchmark", "JT808.DotNetty.CleintBenchmark\JT808.DotNetty.CleintBenchmark.csproj", "{C2B1A0F4-2C49-45DA-9F48-7A016FC6E9E1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.DotNetty.Kafka", "JT808.DotNetty.Kafka\JT808.DotNetty.Kafka.csproj", "{7050DC16-4CD8-406C-9F3B-F085407E94EB}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.DotNetty.Kafka", "JT808.DotNetty.Kafka\JT808.DotNetty.Kafka.csproj", "{576A8394-AA60-4DAE-864B-D4BBB67B8E75}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.DotNetty.RabbitMQ", "JT808.DotNetty.RabbitMQ\JT808.DotNetty.RabbitMQ.csproj", "{48C53550-610E-4CE5-AFE4-E285280A8365}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.DotNetty.Kafka.Test", "JT808.DotNetty.Tests\JT808.DotNetty.Kafka.Test\JT808.DotNetty.Kafka.Test.csproj", "{50A94BD5-5CDF-4777-AE4C-80BA769AEDAB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.DotNetty.RabbitMQ", "JT808.DotNetty.RabbitMQ\JT808.DotNetty.RabbitMQ.csproj", "{BE8F9C65-2F03-4E8A-88D2-0F846D871473}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.DotNetty.RabbitMQ.Test", "JT808.DotNetty.Tests\JT808.DotNetty.RabbitMQ.Test\JT808.DotNetty.RabbitMQ.Test.csproj", "{D3CA0D73-1CCF-41BA-88D8-5BE50515CA64}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -107,14 +111,22 @@ Global
{C2B1A0F4-2C49-45DA-9F48-7A016FC6E9E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2B1A0F4-2C49-45DA-9F48-7A016FC6E9E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2B1A0F4-2C49-45DA-9F48-7A016FC6E9E1}.Release|Any CPU.Build.0 = Release|Any CPU
- {7050DC16-4CD8-406C-9F3B-F085407E94EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7050DC16-4CD8-406C-9F3B-F085407E94EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7050DC16-4CD8-406C-9F3B-F085407E94EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7050DC16-4CD8-406C-9F3B-F085407E94EB}.Release|Any CPU.Build.0 = Release|Any CPU
- {48C53550-610E-4CE5-AFE4-E285280A8365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {48C53550-610E-4CE5-AFE4-E285280A8365}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {48C53550-610E-4CE5-AFE4-E285280A8365}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {48C53550-610E-4CE5-AFE4-E285280A8365}.Release|Any CPU.Build.0 = Release|Any CPU
+ {576A8394-AA60-4DAE-864B-D4BBB67B8E75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {576A8394-AA60-4DAE-864B-D4BBB67B8E75}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {576A8394-AA60-4DAE-864B-D4BBB67B8E75}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {576A8394-AA60-4DAE-864B-D4BBB67B8E75}.Release|Any CPU.Build.0 = Release|Any CPU
+ {50A94BD5-5CDF-4777-AE4C-80BA769AEDAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {50A94BD5-5CDF-4777-AE4C-80BA769AEDAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {50A94BD5-5CDF-4777-AE4C-80BA769AEDAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {50A94BD5-5CDF-4777-AE4C-80BA769AEDAB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BE8F9C65-2F03-4E8A-88D2-0F846D871473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BE8F9C65-2F03-4E8A-88D2-0F846D871473}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BE8F9C65-2F03-4E8A-88D2-0F846D871473}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BE8F9C65-2F03-4E8A-88D2-0F846D871473}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D3CA0D73-1CCF-41BA-88D8-5BE50515CA64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D3CA0D73-1CCF-41BA-88D8-5BE50515CA64}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D3CA0D73-1CCF-41BA-88D8-5BE50515CA64}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D3CA0D73-1CCF-41BA-88D8-5BE50515CA64}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -127,6 +139,8 @@ Global
{A0F2F006-5AEB-454E-83C5-ABFB58DE17A9} = {3BD7FF02-8516-4A77-A385-9FDCDD792E22}
{E6F61CE8-BFB4-4946-A0D3-AECCE77824E5} = {2459FB59-8A33-49A4-ADBC-A0B12C5886A6}
{CCE6AEFB-1AB0-4BD9-8EA2-8B4CDD097E88} = {2459FB59-8A33-49A4-ADBC-A0B12C5886A6}
+ {50A94BD5-5CDF-4777-AE4C-80BA769AEDAB} = {3BD7FF02-8516-4A77-A385-9FDCDD792E22}
+ {D3CA0D73-1CCF-41BA-88D8-5BE50515CA64} = {3BD7FF02-8516-4A77-A385-9FDCDD792E22}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FC0FFCEA-E1EF-4C97-A1C5-F89418B6834B}