Bladeren bron

修改了通信库
使用tdms文件保存实验数据

l2736 2 weken geleden
bovenliggende
commit
1a8cbbeecd
100 gewijzigde bestanden met toevoegingen van 1203 en 4154 verwijderingen
  1. 9 10
      Avalonia/Avalonia.Xaml.Behaviors/Avalonia.Xaml.Behaviors.csproj
  2. 9 3
      Avalonia/Avalonia.Xaml.Behaviors/Properties/AssemblyInfo.cs
  3. 0 28
      Avalonia/Avalonia.Xaml.Interactions.Custom/Avalonia.Xaml.Interactions.Custom.csproj
  4. 101 0
      Avalonia/Avalonia.Xaml.Interactions.Custom/Avalonia.Xaml.Interactions.Custom.projitems
  5. 13 0
      Avalonia/Avalonia.Xaml.Interactions.Custom/Avalonia.Xaml.Interactions.Custom.shproj
  6. 0 25
      Avalonia/Avalonia.Xaml.Interactions.DragAndDrop/Avalonia.Xaml.Interactions.DragAndDrop.csproj
  7. 19 0
      Avalonia/Avalonia.Xaml.Interactions.DragAndDrop/Avalonia.Xaml.Interactions.DragAndDrop.projitems
  8. 13 0
      Avalonia/Avalonia.Xaml.Interactions.DragAndDrop/Avalonia.Xaml.Interactions.DragAndDrop.shproj
  9. 0 6
      Avalonia/Avalonia.Xaml.Interactions.DragAndDrop/Properties/AssemblyInfo.cs
  10. 0 26
      Avalonia/Avalonia.Xaml.Interactions.Draggable/Avalonia.Xaml.Interactions.Draggable.csproj
  11. 20 0
      Avalonia/Avalonia.Xaml.Interactions.Draggable/Avalonia.Xaml.Interactions.Draggable.projitems
  12. 13 0
      Avalonia/Avalonia.Xaml.Interactions.Draggable/Avalonia.Xaml.Interactions.Draggable.shproj
  13. 0 6
      Avalonia/Avalonia.Xaml.Interactions.Draggable/Properties/AssemblyInfo.cs
  14. 0 26
      Avalonia/Avalonia.Xaml.Interactions.Events/Avalonia.Xaml.Interactions.Events.csproj
  15. 33 0
      Avalonia/Avalonia.Xaml.Interactions.Events/Avalonia.Xaml.Interactions.Events.projitems
  16. 13 0
      Avalonia/Avalonia.Xaml.Interactions.Events/Avalonia.Xaml.Interactions.Events.shproj
  17. 0 6
      Avalonia/Avalonia.Xaml.Interactions.Events/Properties/AssemblyInfo.cs
  18. 0 22
      Avalonia/Avalonia.Xaml.Interactions.Responsive/Avalonia.Xaml.Interactions.Responsive.csproj
  19. 15 0
      Avalonia/Avalonia.Xaml.Interactions.Responsive/Avalonia.Xaml.Interactions.Responsive.projitems
  20. 13 0
      Avalonia/Avalonia.Xaml.Interactions.Responsive/Avalonia.Xaml.Interactions.Responsive.shproj
  21. 0 6
      Avalonia/Avalonia.Xaml.Interactions.Responsive/Properties/AssemblyInfo.cs
  22. 0 26
      Avalonia/Avalonia.Xaml.Interactions/Avalonia.Xaml.Interactions.csproj
  23. 18 0
      Avalonia/Avalonia.Xaml.Interactions/Avalonia.Xaml.Interactions.projitems
  24. 13 0
      Avalonia/Avalonia.Xaml.Interactions/Avalonia.Xaml.Interactions.shproj
  25. 0 7
      Avalonia/Avalonia.Xaml.Interactions/Properties/AssemblyInfo.cs
  26. 0 23
      Avalonia/Avalonia.Xaml.Interactivity/Avalonia.Xaml.Interactivity.csproj
  27. 33 0
      Avalonia/Avalonia.Xaml.Interactivity/Avalonia.Xaml.Interactivity.projitems
  28. 13 0
      Avalonia/Avalonia.Xaml.Interactivity/Avalonia.Xaml.Interactivity.shproj
  29. 2 2
      Avalonia/ShakerApp/App.axaml.cs
  30. 16 13
      Avalonia/ShakerApp/ShakerApp.csproj
  31. 0 1
      Avalonia/ShakerApp/Styles/ResourceDictionary.axaml
  32. 4 3
      Avalonia/ShakerApp/Tools/PluginsLoader.cs
  33. 11 14
      Avalonia/ShakerApp/ViewModels/CommunicationViewModel.cs
  34. 214 0
      Avalonia/ShakerApp/ViewModels/DataReview/BaseDataReviewItemViewModel.cs
  35. 97 0
      Avalonia/ShakerApp/ViewModels/DataReview/DataReviewViewModel.cs
  36. 14 0
      Avalonia/ShakerApp/ViewModels/DataReview/IDataReviewItem.cs
  37. 24 0
      Avalonia/ShakerApp/ViewModels/DataReview/OutSignalDataReviewViewModel.cs
  38. 23 0
      Avalonia/ShakerApp/ViewModels/DataReview/RandomDataReviewViewModel.cs
  39. 70 0
      Avalonia/ShakerApp/ViewModels/DataReview/SelectTestDataViewModel.cs
  40. 23 0
      Avalonia/ShakerApp/ViewModels/DataReview/SineDataReviewViewModel.cs
  41. 23 0
      Avalonia/ShakerApp/ViewModels/DataReview/StartPageDataReviewViewModel.cs
  42. 6 4
      Avalonia/ShakerApp/ViewModels/DeviceManger/DeviceInfoViewModel.cs
  43. 2 9
      Avalonia/ShakerApp/ViewModels/Log/LogViewModel.cs
  44. 3 7
      Avalonia/ShakerApp/ViewModels/MainPage/IMainPageViewModel.cs
  45. 4 5
      Avalonia/ShakerApp/ViewModels/MainPage/MainPageViewModel.cs
  46. 9 15
      Avalonia/ShakerApp/ViewModels/MainPage/OutSignalMainPageViewModel.cs
  47. 38 29
      Avalonia/ShakerApp/ViewModels/MainPage/RandomMainPageViewModel.cs
  48. 25 22
      Avalonia/ShakerApp/ViewModels/MainPage/SineMainPageViewModel.cs
  49. 27 9
      Avalonia/ShakerApp/ViewModels/MainViewModel.cs
  50. 9 0
      Avalonia/ShakerApp/ViewModels/Menu/MenuViewModel.cs
  51. 6 5
      Avalonia/ShakerApp/ViewModels/ShakerConfig/ShakerConfigViewModel.cs
  52. 7 7
      Avalonia/ShakerApp/ViewModels/ShakerControl/ShakerControlViewModel.cs
  53. 9 7
      Avalonia/ShakerApp/ViewModels/ShakerDataViewModel.cs
  54. 0 1
      Avalonia/ShakerApp/ViewModels/ViewModelBase.cs
  55. 56 0
      Avalonia/ShakerApp/Views/DataReview/LoadTestDataView.axaml
  56. 13 0
      Avalonia/ShakerApp/Views/DataReview/LoadTestDataView.axaml.cs
  57. 11 0
      Avalonia/ShakerApp/Views/DataReview/OutSignalDataReviewView.axaml
  58. 13 0
      Avalonia/ShakerApp/Views/DataReview/OutSignalDataReviewView.axaml.cs
  59. 8 0
      Avalonia/ShakerApp/Views/DataReview/RandomDataReviewView.axaml
  60. 13 0
      Avalonia/ShakerApp/Views/DataReview/RandomDataReviewView.axaml.cs
  61. 8 0
      Avalonia/ShakerApp/Views/DataReview/SineDataReviewView.axaml
  62. 13 0
      Avalonia/ShakerApp/Views/DataReview/SineDataReviewView.axaml.cs
  63. 11 0
      Avalonia/ShakerApp/Views/DataReview/StartDataReviewView.axaml
  64. 13 0
      Avalonia/ShakerApp/Views/DataReview/StartDataReviewView.axaml.cs
  65. 1 1
      Avalonia/ShakerApp/Views/File/LoadConfigView.axaml
  66. 1 1
      Avalonia/ShakerApp/Views/File/SaveConfigView.axaml
  67. 9 0
      Avalonia/ShakerApp/Views/MainWindow.axaml
  68. 4 5
      Avalonia/SukiUI/SukiUI.csproj
  69. 0 29
      Avalonia/Xaml.Behaviors/Xaml.Behaviors.csproj
  70. 0 12
      Avalonia/Xaml.Interactions/Properties/AssemblyInfo.cs
  71. 0 50
      Avalonia/Xaml.Interactions/Xaml.Interactions.csproj
  72. 0 35
      Avalonia/Xaml.Interactivity/Xaml.Interactivity.csproj
  73. 3 3
      Communication/ActiveMQ/EasyMQ.MessagePackSerializer/EasyMQ.MessagePackSerializer.csproj
  74. 6 1
      Communication/ActiveMQCommunication/ActiveMQCommunication.csproj
  75. 6 1
      Communication/LocalCommunication/LocalCommunication.csproj
  76. 0 311
      Communication/NetMQ/AsyncReceiveExtensions.cs
  77. 0 125
      Communication/NetMQ/AtomicCounterPool.cs
  78. 0 207
      Communication/NetMQ/BufferPool.cs
  79. 0 135
      Communication/NetMQ/Core/Address.cs
  80. 0 62
      Communication/NetMQ/Core/Command.cs
  81. 0 116
      Communication/NetMQ/Core/CommandType.cs
  82. 0 106
      Communication/NetMQ/Core/Config.cs
  83. 0 520
      Communication/NetMQ/Core/Ctx.cs
  84. 0 66
      Communication/NetMQ/Core/ErrorHelper.cs
  85. 0 34
      Communication/NetMQ/Core/HellloMsgSession.cs
  86. 0 11
      Communication/NetMQ/Core/IMailbox.cs
  87. 0 15
      Communication/NetMQ/Core/IMsgSink.cs
  88. 0 17
      Communication/NetMQ/Core/IMsgSource.cs
  89. 0 149
      Communication/NetMQ/Core/IOObject.cs
  90. 0 106
      Communication/NetMQ/Core/IOThread.cs
  91. 0 39
      Communication/NetMQ/Core/IPollEvents.cs
  92. 0 46
      Communication/NetMQ/Core/IProactorEvents.cs
  93. 0 15
      Communication/NetMQ/Core/ITimerEvent.cs
  94. 0 260
      Communication/NetMQ/Core/Mailbox.cs
  95. 0 119
      Communication/NetMQ/Core/MailboxSafe.cs
  96. 0 279
      Communication/NetMQ/Core/Mechanisms/CurveClientMechanism.cs
  97. 0 129
      Communication/NetMQ/Core/Mechanisms/CurveMechanismBase.cs
  98. 0 318
      Communication/NetMQ/Core/Mechanisms/CurveServerMechanism.cs
  99. 0 360
      Communication/NetMQ/Core/Mechanisms/Mechanism.cs
  100. 0 98
      Communication/NetMQ/Core/Mechanisms/NullMechanism.cs

+ 9 - 10
Avalonia/Avalonia.Xaml.Behaviors/Avalonia.Xaml.Behaviors.csproj

@@ -14,18 +14,17 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.2.2" />
+    <PackageReference Include="Avalonia" Version="11.2.3" />
+    <PackageReference Include="System.Reactive" Version="6.0.1" />
   </ItemGroup>
   <Import Project="..\build\SignAssembly.props" />
+  <Import Project="..\Avalonia.Xaml.Interactivity\Avalonia.Xaml.Interactivity.projitems" Label="Shared" />
+  <Import Project="..\Avalonia.Xaml.Interactions.Responsive\Avalonia.Xaml.Interactions.Responsive.projitems" Label="Shared" />
+  <Import Project="..\Avalonia.Xaml.Interactions.Events\Avalonia.Xaml.Interactions.Events.projitems" Label="Shared" />
+  <Import Project="..\Avalonia.Xaml.Interactions.Draggable\Avalonia.Xaml.Interactions.Draggable.projitems" Label="Shared" />
+  <Import Project="..\Avalonia.Xaml.Interactions.DragAndDrop\Avalonia.Xaml.Interactions.DragAndDrop.projitems" Label="Shared" />
+  <Import Project="..\Avalonia.Xaml.Interactions.Custom\Avalonia.Xaml.Interactions.Custom.projitems" Label="Shared" />
+  <Import Project="..\Avalonia.Xaml.Interactions\Avalonia.Xaml.Interactions.projitems" Label="Shared" />
   <Import Project="..\build\TrimmingEnable.targets" />
-  <ItemGroup>
-    <ProjectReference Include="..\Avalonia.Xaml.Interactions.Custom\Avalonia.Xaml.Interactions.Custom.csproj" />
-    <ProjectReference Include="..\Avalonia.Xaml.Interactions.DragAndDrop\Avalonia.Xaml.Interactions.DragAndDrop.csproj" />
-    <ProjectReference Include="..\Avalonia.Xaml.Interactions.Draggable\Avalonia.Xaml.Interactions.Draggable.csproj" />
-    <ProjectReference Include="..\Avalonia.Xaml.Interactions.Events\Avalonia.Xaml.Interactions.Events.csproj" />
-    <ProjectReference Include="..\Avalonia.Xaml.Interactions.Responsive\Avalonia.Xaml.Interactions.Responsive.csproj" />
-    <ProjectReference Include="..\Avalonia.Xaml.Interactions\Avalonia.Xaml.Interactions.csproj" />
-    <ProjectReference Include="..\Avalonia.Xaml.Interactivity\Avalonia.Xaml.Interactivity.csproj" />
-  </ItemGroup>
 
 </Project>

+ 9 - 3
Avalonia/Avalonia.Xaml.Interactivity/Properties/AssemblyInfo.cs → Avalonia/Avalonia.Xaml.Behaviors/Properties/AssemblyInfo.cs

@@ -1,7 +1,7 @@
 using System.Runtime.CompilerServices;
 using Avalonia.Metadata;
 
-[assembly: InternalsVisibleTo("Avalonia.Xaml.Interactivity.UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
+[assembly: InternalsVisibleTo("Avalonia.Xaml.Interactivity, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
 [assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
 [assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.Custom, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
 [assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.DragAndDrop, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
@@ -10,6 +10,12 @@ using Avalonia.Metadata;
 [assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.Custom, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
 [assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.Responsive, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
 
-[assembly: InternalsVisibleTo("Xaml.Interactions, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
-
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions")]
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Core")]
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Custom")]
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.DragAndDrop")]
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Draggable")]
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Events")]
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Responsive")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactivity")]
+

+ 0 - 28
Avalonia/Avalonia.Xaml.Interactions.Custom/Avalonia.Xaml.Interactions.Custom.csproj

@@ -1,28 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Avalonia.Xaml.Interactions.Custom</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.2.2" />
-    <PackageReference Include="System.Reactive" Version="6.0.1" />
-  </ItemGroup>
-
-  <Import Project="..\build\SignAssembly.props" />
-  <Import Project="..\build\TrimmingEnable.targets" />
-
-  <ItemGroup>
-    <ProjectReference Include="..\Avalonia.Xaml.Interactivity\Avalonia.Xaml.Interactivity.csproj" />
-  </ItemGroup>
-
-</Project>

+ 101 - 0
Avalonia/Avalonia.Xaml.Interactions.Custom/Avalonia.Xaml.Interactions.Custom.projitems

@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>b2f07c20-6b85-4a6f-bb58-b379513da5f9</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>Avalonia.Xaml.Interactions.Custom</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Actions\AddClassAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Actions\ChangeAvaloniaPropertyAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Actions\CloseNotificationAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Actions\FocusControlAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Actions\PopupAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Actions\RemoveClassAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Animations\FadeInBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)AutoCompleteBox\FocusAutoCompleteBoxTextBoxBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)BindPointerOverBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)BindTagToVisualRootDataContextBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)BoundsObserverBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Button\ButtonClickEventTriggerBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Button\ButtonExecuteCommandOnKeyDownBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Button\ButtonHideFlyoutBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Button\ButtonHideFlyoutOnClickBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Composition\SelectingItemsControlBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Composition\SlidingAnimation.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\AttachedToLogicalTreeBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\AttachedToVisualTreeBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\BindingBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\DisposingBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\DisposingTrigger.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\KeyDownTrigger.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\LoadedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\RoutedEventTriggerBase.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\RoutedEventTriggerBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\ValueChangedTriggerBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)DragControlBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\Core\ExecuteCommandBehaviorBase.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\Core\ExecuteCommandOnKeyBehaviorBase.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\Core\ExecuteCommandRoutedEventBehaviorBase.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnActivatedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnDoubleTappedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnGotFocusBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnHoldingBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnKeyDownBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnKeyUpBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnLostFocusBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPinchBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPinchEndedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerCaptureLostBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerEnteredBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerExitedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerMovedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerPressedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerReleasedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerTouchPadGestureMagnifyBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerTouchPadGestureRotateBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerTouchPadGestureSwipeBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPointerWheelChangedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPullGestureBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnPullGestureEndedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnRightTappedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnScrollGestureBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnScrollGestureEndedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnScrollGestureInertiaStartingBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnTappedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnTextInputBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ExecuteCommand\ExecuteCommandOnTextInputMethodClientRequestedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Focus\FocusBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Focus\FocusBehaviorBase.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Focus\FocusControlBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Focus\FocusOnAttachedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Focus\FocusOnAttachedToVisualTreeBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Focus\FocusOnPointerMovedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Focus\FocusOnPointerPressedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Focus\FocusSelectedItemBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)HideAttachedFlyoutBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)HideOnKeyPressedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)HideOnLostFocusBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ItemsControl\ItemNudgeDropBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ItemsControl\ItemsControlContainerEventsBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ItemsControl\ScrollToItemBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ItemsControl\ScrollToItemIndexBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ListBoxItem\SelectListBoxItemOnPointerMovedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ListBox\ListBoxSelectAllBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ListBox\ListBoxUnselectAllBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ScrollViewer\HorizontalScrollViewerBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)SelectingItemsControl\SelectingItemsControlEventsBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ShowPointerPositionBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Show\ShowBehaviorBase.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Show\ShowOnDoubleTappedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Show\ShowOnKeyDownBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Show\ShowOnTappedBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TextBox\TextBoxSelectAllOnGotFocusBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TextBox\TextBoxSelectAllTextBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TreeViewItem\ToggleIsExpandedOnDoubleTappedBehavior.cs" />
+  </ItemGroup>
+</Project>

+ 13 - 0
Avalonia/Avalonia.Xaml.Interactions.Custom/Avalonia.Xaml.Interactions.Custom.shproj

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>b2f07c20-6b85-4a6f-bb58-b379513da5f9</ProjectGuid>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <PropertyGroup />
+  <Import Project="Avalonia.Xaml.Interactions.Custom.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 0 - 25
Avalonia/Avalonia.Xaml.Interactions.DragAndDrop/Avalonia.Xaml.Interactions.DragAndDrop.csproj

@@ -1,25 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Avalonia.Xaml.Interactions.DragAndDrop</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.2.2" />
-  </ItemGroup>
-  <Import Project="..\build\SignAssembly.props" />
-  <Import Project="..\build\TrimmingEnable.targets" />
-  <ItemGroup>
-    <ProjectReference Include="..\Avalonia.Xaml.Interactivity\Avalonia.Xaml.Interactivity.csproj" />
-  </ItemGroup>
-
-</Project>

+ 19 - 0
Avalonia/Avalonia.Xaml.Interactions.DragAndDrop/Avalonia.Xaml.Interactions.DragAndDrop.projitems

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>4064507c-1536-4c90-a881-bc5a3459005d</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>Avalonia.Xaml.Interactions.DragAndDrop</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)ContextDragBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ContextDropBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)DropHandlerBase.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)IDragHandler.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)IDropHandler.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TypedDragBehavior.cs" />
+  </ItemGroup>
+</Project>

+ 13 - 0
Avalonia/Avalonia.Xaml.Interactions.DragAndDrop/Avalonia.Xaml.Interactions.DragAndDrop.shproj

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>4064507c-1536-4c90-a881-bc5a3459005d</ProjectGuid>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <PropertyGroup />
+  <Import Project="Avalonia.Xaml.Interactions.DragAndDrop.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 0 - 6
Avalonia/Avalonia.Xaml.Interactions.DragAndDrop/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-using System.Runtime.CompilerServices;
-using Avalonia.Metadata;
-
-[assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
-
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.DragAndDrop")]

+ 0 - 26
Avalonia/Avalonia.Xaml.Interactions.Draggable/Avalonia.Xaml.Interactions.Draggable.csproj

@@ -1,26 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Avalonia.Xaml.Interactions.Draggable</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.2.2" />
-  </ItemGroup>
-
-  <Import Project="..\build\SignAssembly.props" />
-  <Import Project="..\build\TrimmingEnable.targets" />
-  <ItemGroup>
-    <ProjectReference Include="..\Avalonia.Xaml.Interactivity\Avalonia.Xaml.Interactivity.csproj" />
-  </ItemGroup>
-
-</Project>

+ 20 - 0
Avalonia/Avalonia.Xaml.Interactions.Draggable/Avalonia.Xaml.Interactions.Draggable.projitems

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>92f01e90-01ff-40ce-8ae3-28fb88122a33</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>Avalonia.Xaml.Interactions.Draggable</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)CanvasDragBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)GridDragBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ItemDragBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)SelectionAdorner.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(MSBuildThisFileDirectory)Styles.axaml" />
+  </ItemGroup>
+</Project>

+ 13 - 0
Avalonia/Avalonia.Xaml.Interactions.Draggable/Avalonia.Xaml.Interactions.Draggable.shproj

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>92f01e90-01ff-40ce-8ae3-28fb88122a33</ProjectGuid>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <PropertyGroup />
+  <Import Project="Avalonia.Xaml.Interactions.Draggable.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 0 - 6
Avalonia/Avalonia.Xaml.Interactions.Draggable/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-using System.Runtime.CompilerServices;
-using Avalonia.Metadata;
-
-[assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
-
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Draggable")]

+ 0 - 26
Avalonia/Avalonia.Xaml.Interactions.Events/Avalonia.Xaml.Interactions.Events.csproj

@@ -1,26 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Avalonia.Xaml.Interactions.Events</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.2.2" />
-  </ItemGroup>
-  <Import Project="..\build\SignAssembly.props" />
-  <Import Project="..\build\TrimmingEnable.targets" />
-
-  <ItemGroup>
-    <ProjectReference Include="..\Avalonia.Xaml.Interactivity\Avalonia.Xaml.Interactivity.csproj" />
-  </ItemGroup>
-
-</Project>

+ 33 - 0
Avalonia/Avalonia.Xaml.Interactions.Events/Avalonia.Xaml.Interactions.Events.projitems

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>8c66cbf0-ccb2-48ff-9a9b-e39ccc5a68b7</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>Avalonia.Xaml.Interactions.Events</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Core\InteractiveBehaviorBase.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)DoubleTappedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)GotFocusEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)KeyDownEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)KeyUpEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)LostFocusEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)PointerCaptureLostEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)PointerEnteredEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)PointerEventsBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)PointerExitedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)PointerMovedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)PointerPressedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)PointerReleasedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)PointerWheelChangedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)RightTappedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ScrollGestureEndedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ScrollGestureEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TappedEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TextInputEventBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TextInputMethodClientRequestedEventBehavior.cs" />
+  </ItemGroup>
+</Project>

+ 13 - 0
Avalonia/Avalonia.Xaml.Interactions.Events/Avalonia.Xaml.Interactions.Events.shproj

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>8c66cbf0-ccb2-48ff-9a9b-e39ccc5a68b7</ProjectGuid>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <PropertyGroup />
+  <Import Project="Avalonia.Xaml.Interactions.Events.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 0 - 6
Avalonia/Avalonia.Xaml.Interactions.Events/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-using System.Runtime.CompilerServices;
-using Avalonia.Metadata;
-
-[assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
-
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Events")]

+ 0 - 22
Avalonia/Avalonia.Xaml.Interactions.Responsive/Avalonia.Xaml.Interactions.Responsive.csproj

@@ -1,22 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Avalonia.Xaml.Interactions.Responsive</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-
-  <ItemGroup>
-    <ProjectReference Include="..\Avalonia.Xaml.Interactivity\Avalonia.Xaml.Interactivity.csproj" />
-  </ItemGroup>
-  <Import Project="..\build\SignAssembly.props" />
-  <Import Project="..\build\TrimmingEnable.targets" />
-</Project>

+ 15 - 0
Avalonia/Avalonia.Xaml.Interactions.Responsive/Avalonia.Xaml.Interactions.Responsive.projitems

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>33c2c0a8-f484-4f92-8de8-71ff1aaec529</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>Avalonia.Xaml.Interactions.Responsive</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)AdaptiveBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)AdaptiveClassSetter.cs" />
+  </ItemGroup>
+</Project>

+ 13 - 0
Avalonia/Avalonia.Xaml.Interactions.Responsive/Avalonia.Xaml.Interactions.Responsive.shproj

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>33c2c0a8-f484-4f92-8de8-71ff1aaec529</ProjectGuid>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <PropertyGroup />
+  <Import Project="Avalonia.Xaml.Interactions.Responsive.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 0 - 6
Avalonia/Avalonia.Xaml.Interactions.Responsive/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-using System.Runtime.CompilerServices;
-using Avalonia.Metadata;
-
-[assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
-
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Responsive")]

+ 0 - 26
Avalonia/Avalonia.Xaml.Interactions/Avalonia.Xaml.Interactions.csproj

@@ -1,26 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Avalonia.Xaml.Interactions</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.2.2" />
-  </ItemGroup>
-  <Import Project="..\build\SignAssembly.props" />
-  <Import Project="..\build\TrimmingEnable.targets" />
-
-  <ItemGroup>
-    <ProjectReference Include="..\Avalonia.Xaml.Interactivity\Avalonia.Xaml.Interactivity.csproj" />
-  </ItemGroup>
-
-</Project>

+ 18 - 0
Avalonia/Avalonia.Xaml.Interactions/Avalonia.Xaml.Interactions.projitems

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>4f0ab147-be84-4a40-98d0-330a387b1201</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>Avalonia.Xaml.Interactions</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Core\CallMethodAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\ChangePropertyAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\DataTriggerBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\EventTriggerBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\InvokeCommandAction.cs" />
+  </ItemGroup>
+</Project>

+ 13 - 0
Avalonia/Avalonia.Xaml.Interactions/Avalonia.Xaml.Interactions.shproj

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>4f0ab147-be84-4a40-98d0-330a387b1201</ProjectGuid>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <PropertyGroup />
+  <Import Project="Avalonia.Xaml.Interactions.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 0 - 7
Avalonia/Avalonia.Xaml.Interactions/Properties/AssemblyInfo.cs

@@ -1,7 +0,0 @@
-using System.Runtime.CompilerServices;
-using Avalonia.Metadata;
-
-[assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
-
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions")]
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Core")]

+ 0 - 23
Avalonia/Avalonia.Xaml.Interactivity/Avalonia.Xaml.Interactivity.csproj

@@ -1,23 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Avalonia.Xaml.Interactivity</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.2.2" />
-  </ItemGroup>
-  <Import Project="..\build\SignAssembly.props" />
-  <Import Project="..\build\TrimmingEnable.targets" />
-
-
-</Project>

+ 33 - 0
Avalonia/Avalonia.Xaml.Interactivity/Avalonia.Xaml.Interactivity.projitems

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>3279e103-e03f-4d4d-a6ee-27250c33baa7</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>Avalonia.Xaml.Interactivity</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Action.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ActionCollection.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Behavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)BehaviorCollection.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)BehaviorCollectionTemplate.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)BehaviorOfT.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ComparisonConditionType.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)IAction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)IBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)IBehaviorEventsHandler.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interaction.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ITrigger.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)StyledElementBehavior.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)StyledElementBehaviorOfT.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)StyledElementTrigger.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)StyledElementTriggerOfT.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\CodeAnalysis\TrimmingAttributes.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Trigger.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TriggerOfT.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TypeConverterHelper.cs" />
+  </ItemGroup>
+</Project>

+ 13 - 0
Avalonia/Avalonia.Xaml.Interactivity/Avalonia.Xaml.Interactivity.shproj

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>3279e103-e03f-4d4d-a6ee-27250c33baa7</ProjectGuid>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <PropertyGroup />
+  <Import Project="Avalonia.Xaml.Interactivity.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 2 - 2
Avalonia/ShakerApp/App.axaml.cs

@@ -42,8 +42,8 @@ public partial class App : Application
             desktop.MainWindow = new MainWindow();
         }
         base.OnFrameworkInitializationCompleted();
-        Window1 window = new Window1();
-        window.Show();
+        //Window1 window = new Window1();
+        //window.Show();
     }
 
 }

+ 16 - 13
Avalonia/ShakerApp/ShakerApp.csproj

@@ -27,21 +27,17 @@
 
 
   <ItemGroup>
-    <PackageReference Include="Avalonia.Controls.ColorPicker" Version="11.2.2" />
-    <PackageReference Include="Avalonia.Desktop" Version="11.2.2" />
-    <PackageReference Include="Avalonia.Markup.Xaml.Loader" Version="11.2.2" />
-    <PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
-    <PackageReference Include="Avalonia.Diagnostics" Version="11.2.1">
+    <PackageReference Include="Avalonia.Desktop" Version="11.2.3" />
+    <PackageReference Include="Avalonia.Markup.Xaml.Loader" Version="11.2.3" />
+    <PackageReference Include="Avalonia.Themes.Simple" Version="11.2.3" />
+    <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
+    <PackageReference Include="Avalonia.Diagnostics" Version="11.2.3">
       <IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
       <PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
     </PackageReference>
-    <PackageReference Include="DotNetty.Handlers" Version="0.7.6" />
-    <PackageReference Include="DotNetty.Transport.Libuv" Version="0.7.6" />
-    <PackageReference Condition="'$(Configuration)'=='Debug'" Include="HotAvalonia" Version="2.0.2" />
-    <PackageReference Condition="'$(Configuration)'=='Debug'" Include="HotAvalonia.Extensions" Version="2.0.0" />
-    <PackageReference Include="MessagePack" Version="3.0.308" />
-    <PackageReference Condition="'$(Configuration)'=='Debug'" Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
-    <PackageReference Include="ParquetSharp" Version="16.1.0" />
+    <PackageReference Condition="'$(Configuration)'=='Debug'" Include="HotAvalonia" Version="2.1.0" />
+    <PackageReference Condition="'$(Configuration)'=='Debug'" Include="HotAvalonia.Extensions" Version="2.1.0" />
+    <PackageReference Include="MessagePack" Version="3.1.3" />
     <PackageReference Include="System.ServiceModel.Primitives" Version="8.1.1" />
   </ItemGroup>
 
@@ -57,6 +53,13 @@
   </ItemGroup>
 
   <ItemGroup>
-    <Folder Include="ViewModels\DataReview\" />
+    <Compile Update="Views\DataReview\LoadTestDataView.axaml.cs">
+      <DependentUpon>LoadTestDataView.axaml</DependentUpon>
+    </Compile>
+    <Compile Update="Views\DataReview\RandomDataReviewView.axaml.cs">
+      <DependentUpon>RandomDataReviewView.axaml</DependentUpon>
+    </Compile>
   </ItemGroup>
+
+  <Import Project="..\..\TDMS\TDMS.projitems" Label="Shared" />
 </Project>

File diff suppressed because it is too large
+ 0 - 1
Avalonia/ShakerApp/Styles/ResourceDictionary.axaml


+ 4 - 3
Avalonia/ShakerApp/Tools/PluginsLoader.cs

@@ -11,7 +11,7 @@ namespace ShakerApp.Tools
 {
     public class PluginsLoader
     {
-        private string _Path = "";
+        private string ext = "";
         private List<Assembly> LoadedAssemblies = new List<Assembly>();
 
         [AllowNull]
@@ -27,7 +27,6 @@ namespace ShakerApp.Tools
         {
             try
             {
-                _Path = path;
                 resolver = new AssemblyDependencyResolver(path);
                 AssemblyLoadContext.Default.Resolving += Default_Resolving;
                 AssemblyLoadContext.Default.ResolvingUnmanagedDll += Default_ResolvingUnmanagedDll;
@@ -70,7 +69,9 @@ namespace ShakerApp.Tools
         {
             var fileinfo = new FileInfo(arg1.Location);
             if (fileinfo?.Directory == null) return 0;
-            var file = fileinfo.Directory.GetFiles(arg2, SearchOption.AllDirectories).FirstOrDefault()?.FullName;
+            string ext = "*.dll";
+            var file = fileinfo.Directory.GetFiles(ext, SearchOption.AllDirectories).FirstOrDefault(x=>x.Name == arg2)?.FullName;
+            
             if (System.IO.File.Exists(file))
             {
                 return LoadLibrary(file);

+ 11 - 14
Avalonia/ShakerApp/ViewModels/CommunicationViewModel.cs

@@ -31,6 +31,14 @@ namespace ShakerApp.ViewModels
         static CommunicationViewModel()
         {
 
+        }
+        private async void LocalLocalCommunicationDisconnect()
+        {
+            await Task.Delay(1);//释放线程
+            LogViewModel.Instance.AddLog($"{LocalCommunication.IP}:{LocalCommunication.Port}连接断开", LogType.Error);
+            LocalIsConnect = false;
+            MainViewModel.Default.ShowToast(App.Current?.FindResource("DisConnect") + "", Avalonia.Controls.Notifications.NotificationType.Error);
+            GetEvent(Topic.DisConnect).Publish(this, null);
         }
         public void Connect(string ip,int port)
         {
@@ -40,13 +48,7 @@ namespace ShakerApp.ViewModels
                 if (LocalCommunication == null)
                 {
                     LocalCommunication = (ICommunication.ICommunication)Activator.CreateInstance(CommunicationViewModelTypes[ShakerSettingViewModel.Instance.RemoteControlModel == Models.RemoteControlModel.Lan])!;
-                    LocalCommunication.Disconnected += (_, _) =>
-                    {
-                        LogViewModel.Instance.AddLog($"{LocalCommunication.IP}:{LocalCommunication.Port}连接断开", LogType.Error);
-                        LocalIsConnect = false;
-                        MainViewModel.Default.ShowToast(App.Current?.FindResource("DisConnect") + "", Avalonia.Controls.Notifications.NotificationType.Error);
-                        GetEvent(Topic.DisConnect).Publish(this, null);                        
-                    };
+                    LocalCommunication.Disconnected += (_, _) => LocalLocalCommunicationDisconnect();
                 }
                 if (LocalCommunication!.IsLan == (ShakerSettingViewModel.Instance.RemoteControlModel == Models.RemoteControlModel.Lan))
                 {
@@ -55,13 +57,7 @@ namespace ShakerApp.ViewModels
                 else
                 {
                     LocalCommunication = (ICommunication.ICommunication)Activator.CreateInstance(CommunicationViewModelTypes[ShakerSettingViewModel.Instance.RemoteControlModel == Models.RemoteControlModel.Lan])!;
-                    LocalCommunication.Disconnected += (_, _) =>
-                    {
-                        LogViewModel.Instance.AddLog($"{LocalCommunication.IP}:{LocalCommunication.Port}连接断开", LogType.Error);
-                        LocalIsConnect = false;
-                        MainViewModel.Default.ShowToast( App.Current?.FindResource("DisConnect") + "", Avalonia.Controls.Notifications.NotificationType.Error);
-                        GetEvent(Topic.DisConnect).Publish(this, null);
-                    };
+                    LocalCommunication.Disconnected += (_, _) => LocalLocalCommunicationDisconnect();
                 }
                 LocalCommunication.Connect(ip, port);
                 Thread.Sleep(50);
@@ -183,6 +179,7 @@ namespace ShakerApp.ViewModels
                 MenuViewModel.Instance["MenuDisConnect"]!.IsEnabled = value;
                 MenuViewModel.Instance["MenuDeviceConfig"]!.IsEnabled = value;
                 MenuViewModel.Instance["MenuDebug"]!.IsEnabled = value;
+                MenuViewModel.Instance["MenuTest"]!.IsEnabled = value;
             }
         }
         public bool ServiceIsStart 

+ 214 - 0
Avalonia/ShakerApp/ViewModels/DataReview/BaseDataReviewItemViewModel.cs

@@ -0,0 +1,214 @@
+using Shaker.Models;
+using System;
+using System.Collections;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+
+namespace ShakerApp.ViewModels
+{
+    internal abstract class BaseDataReviewItemViewModel:DisplayViewModelBase<IModel>,IDataReviewItem
+    {
+        private protected ShakerConfigModel ShakerConfig = new ShakerConfigModel();
+        private protected ShakerControlModel ShakerControl = new ShakerControlModel();
+        private protected DeviceInfoModel DeviceInfo = new DeviceInfoModel();
+        private protected bool isopen = false;
+        public bool IsOpen => isopen;
+        public abstract MainPageType PageType { get; }
+        public string File { get; } = string.Empty;
+        [AllowNull]
+        private protected TDMS.ITDMSFile tdmsfile;
+        public virtual void OpenFile(string path) 
+        {
+            tdmsfile?.Close();
+            tdmsfile?.Dispose();
+            tdmsfile = TDMS.TDMSDataBuilder.OpenExisting(path);
+            isopen = true;
+            InitConfig();
+        }
+        public virtual void InitData(TDMS.ITDMSFile file)
+        {
+            tdmsfile?.Close();
+            tdmsfile?.Dispose();
+            tdmsfile = file;
+            isopen = true;
+            InitConfig();
+        }
+        private protected virtual void InitConfig()
+        {
+            if (tdmsfile == null) return;
+            var group = tdmsfile.Contains(nameof(ShakerConfigModel)) ? tdmsfile[nameof(ShakerConfigModel)] : null;
+            if (group == null) return;
+            GetConfig(ref ShakerConfig, group!);
+            group = tdmsfile.Contains(nameof(ShakerControlModel)) ? tdmsfile[nameof(ShakerControlModel)] : null;
+            if (group == null) return;
+            GetConfig(ref ShakerControl, group!);
+            group = tdmsfile.Contains(nameof(DeviceInfoModel)) ? tdmsfile[nameof(DeviceInfoModel)] : null;
+            if (group == null) return;
+            GetConfig(ref DeviceInfo, group!);
+        }
+
+        private protected void GetConfig<T>(ref T config,TDMS.ITDMSChannelGroup group)
+        {
+            typeof(T).GetType()
+                .GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
+                .ToList()
+                .ForEach(x =>
+                {
+                    if (x.FieldType.IsAssignableTo(typeof(IList)) || x.FieldType.IsArray)
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val))
+                        {
+                            byte[] bytes = new byte[val.Length / 2];
+                            for (int i = 0; i < bytes.Length; i++)
+                            {
+                                bytes[i] = System.Convert.ToByte(val.Substring(i * 2, 2), 16);
+                            }
+                            x.SetValue(MessagePack.MessagePackSerializer.Deserialize(x.FieldType, bytes), ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue(Activator.CreateInstance(x.FieldType), ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType.IsEnum)
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val))
+                        {
+                            x.SetValue(Enum.Parse(x.FieldType, val), ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue(Enum.GetValues(x.FieldType), ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(byte))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && byte.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((byte)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(sbyte))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && sbyte.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((sbyte)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(short))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && short.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((short)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(ushort))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && ushort.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((ushort)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(int))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && int.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((int)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(uint))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && uint.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((uint)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(long))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && long.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((long)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(ulong))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && ulong.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((ulong)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(float))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && float.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((float)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(double))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && double.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue((double)0, ShakerConfig);
+                        }
+                    }
+                    else if (x.FieldType == typeof(bool))
+                    {
+                        if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && bool.TryParse(val, out var b))
+                        {
+                            x.SetValue(b, ShakerConfig);
+                        }
+                        else
+                        {
+                            x.SetValue(false, ShakerConfig);
+                        }
+                    }
+                });
+        }
+        public virtual void CloseFile() 
+        {
+            tdmsfile?.Close();
+            tdmsfile?.Dispose();
+            tdmsfile = null;
+        }
+    }
+}

+ 97 - 0
Avalonia/ShakerApp/ViewModels/DataReview/DataReviewViewModel.cs

@@ -0,0 +1,97 @@
+using Avalonia.Controls.Documents;
+using Avalonia.Platform;
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+
+namespace ShakerApp.ViewModels
+{
+    internal class DataReviewViewModel:DisplayViewModelBase<IModel>
+    {
+        private Dictionary<MainPageType, IDataReviewItem> DataReviews = new Dictionary<MainPageType, IDataReviewItem>();
+        [AllowNull]
+        private IDataReviewItem currentDataReview;
+
+        public IDataReviewItem GetDataReview(string path)
+        {
+            var type = GetMainPageType(path);
+            return DataReviews[type];
+        }
+        public static MainPageType GetMainPageType(string path)
+        {
+            try
+            {
+                var tdmsfile = TDMS.TDMSDataBuilder.OpenExisting(path);
+                if(tdmsfile!=null)
+                {
+                    tdmsfile.TryGetProperty<string>(nameof(MainPageViewModel.MainPageType), out var type);
+                    tdmsfile.Close();
+                    return Enum.Parse<MainPageType>(type);
+                }
+            }
+            catch
+            {
+
+            }
+            return MainPageType.StartPage;
+        }
+        private DataReviewViewModel()
+        {
+            DataReviews[MainPageType.StartPage] = StartPageDataReviewViewModel.Instance;
+            DataReviews[MainPageType.RandomPage] = RandomDataReviewViewModel.Instance;
+            DataReviews[MainPageType.SinePage] = SineDataReviewViewModel.Instance;
+            DataReviews[MainPageType.OutSignal] = OutSignalDataReviewViewModel.Instance;
+            CurrentDataReview = DataReviews[MainPageType.StartPage];
+        }
+        static DataReviewViewModel()
+        {
+
+        }
+        public IDataReviewItem CurrentDataReview { get => currentDataReview; set =>SetProperty(ref currentDataReview , value); }
+        public static DataReviewViewModel Instance { get; } = new DataReviewViewModel();
+        public void OpenFile(string path)
+        {
+            CurrentDataReview?.CloseFile();
+            MainPageType maintype = MainPageType.StartPage;
+            try
+            {
+                var tdmsfile = TDMS.TDMSDataBuilder.OpenExisting(path);
+                if (tdmsfile != null)
+                {
+                    if (tdmsfile.IsOpen)
+                    {
+                        tdmsfile.TryGetProperty<string>(nameof(MainPageViewModel.MainPageType), out var type);
+                        if(string.IsNullOrEmpty(type))
+                        {
+                            tdmsfile?.Close();
+                            CurrentDataReview = DataReviews[MainPageType.StartPage];
+                            return;
+                        }
+                        maintype = Enum.Parse<MainPageType>(type);
+                        CurrentDataReview = DataReviews[maintype];
+                        CurrentDataReview.InitData(tdmsfile);
+                        return;
+                    }
+                    else
+                    {
+                        tdmsfile?.Close();
+                    }
+                }
+            }
+            catch
+            {
+
+            }
+            CurrentDataReview = DataReviews[MainPageType.StartPage];
+        }
+        public void CloseFile()
+        {
+            CurrentDataReview?.CloseFile();
+            CurrentDataReview = DataReviews[MainPageType.StartPage];
+        }
+    }
+}

+ 14 - 0
Avalonia/ShakerApp/ViewModels/DataReview/IDataReviewItem.cs

@@ -0,0 +1,14 @@
+using Shaker.Models;
+
+namespace ShakerApp.ViewModels
+{
+    internal interface IDataReviewItem
+    {
+        public bool IsOpen { get; }
+        public MainPageType PageType { get; }
+        public string File { get; }
+        public void OpenFile(string path);
+        public void CloseFile();
+        public void InitData(TDMS.ITDMSFile file);
+    }
+}

+ 24 - 0
Avalonia/ShakerApp/ViewModels/DataReview/OutSignalDataReviewViewModel.cs

@@ -0,0 +1,24 @@
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerApp.ViewModels
+{
+    internal class OutSignalDataReviewViewModel:BaseDataReviewItemViewModel
+    {
+        private OutSignalDataReviewViewModel()
+        {
+            Content = typeof(Views.OutSignalDataReviewView);
+        }
+        static OutSignalDataReviewViewModel()
+        {
+
+        }
+        public static OutSignalDataReviewViewModel Instance { get; } = new OutSignalDataReviewViewModel();
+
+        public override MainPageType PageType =>  MainPageType.OutSignal;
+    }
+}

+ 23 - 0
Avalonia/ShakerApp/ViewModels/DataReview/RandomDataReviewViewModel.cs

@@ -0,0 +1,23 @@
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerApp.ViewModels
+{
+    internal class RandomDataReviewViewModel : BaseDataReviewItemViewModel
+    {
+        public override MainPageType PageType => MainPageType.RandomPage;
+        private RandomDataReviewViewModel()
+        {
+            Content = typeof(Views.RandomDataReviewView);
+        }
+        static RandomDataReviewViewModel()
+        {
+
+        }
+        public static RandomDataReviewViewModel Instance { get; } = new RandomDataReviewViewModel();
+    }
+}

+ 70 - 0
Avalonia/ShakerApp/ViewModels/DataReview/SelectTestDataViewModel.cs

@@ -0,0 +1,70 @@
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Controls;
+using Avalonia.Platform.Storage;
+using CommunityToolkit.Mvvm.Input;
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using Avalonia;
+
+namespace ShakerApp.ViewModels
+{
+    internal class SelectTestDataViewModel:DisplayViewModelBase<IModel>
+    {
+        public override string OKContent => "Confirm";
+        public override bool CanResize => false;
+        public override double Height => 320;
+        public override double Width => 620;
+        private string selectedFile = string.Empty;
+
+        private SelectTestDataViewModel()
+        {
+            Content = typeof(Views.LoadTestDataView);
+        }
+        static SelectTestDataViewModel()
+        {
+
+        }
+        public string SelectedFile { get => selectedFile; set => SetProperty(ref selectedFile, value); }
+        public override void InitData()
+        {
+            base.InitData();
+            SelectedFile = string.Empty;
+        }
+        protected override async void Save()
+        {
+            base.Save();
+            if(!string.IsNullOrEmpty(SelectedFile) && System.IO.File.Exists(SelectedFile))
+            {
+                await Task.Delay(1);
+                DataReviewViewModel.Instance.OpenFile(SelectedFile);
+            }
+        }
+
+        public ICommand SelectFileCommand => new RelayCommand<string?>(SelectFile);
+        private async void SelectFile(string? p)
+        {
+            if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            {
+                var folder = await TopLevel.GetTopLevel(desktop.MainWindow)!.StorageProvider.OpenFilePickerAsync(new Avalonia.Platform.Storage.FilePickerOpenOptions()
+                {
+                    AllowMultiple = false,
+                    Title = p == null ? "" : App.Current?.FindResource(p) + "",
+                    FileTypeFilter = new FilePickerFileType[]
+                    {
+                        new FilePickerFileType($"{(p ==null ?"": App.Current?.FindResource(p) + "")}"){ Patterns = new []{"*.tdms" } }
+                    }
+                });
+                if (folder != null && folder.Count > 0)
+                {
+                    SelectedFile = folder.First().Path.LocalPath;
+                }
+            }
+        }
+        public static SelectTestDataViewModel Instance { get; } = new SelectTestDataViewModel();
+    }
+}

+ 23 - 0
Avalonia/ShakerApp/ViewModels/DataReview/SineDataReviewViewModel.cs

@@ -0,0 +1,23 @@
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerApp.ViewModels
+{
+    internal class SineDataReviewViewModel : BaseDataReviewItemViewModel
+    {
+        public override MainPageType PageType => MainPageType.SinePage;
+        private SineDataReviewViewModel()
+        {
+            Content = typeof(Views.SineDataReviewView);
+        }
+        static SineDataReviewViewModel()
+        {
+
+        }
+        public static SineDataReviewViewModel Instance { get; } = new SineDataReviewViewModel();
+    }
+}

+ 23 - 0
Avalonia/ShakerApp/ViewModels/DataReview/StartPageDataReviewViewModel.cs

@@ -0,0 +1,23 @@
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerApp.ViewModels
+{
+    internal class StartPageDataReviewViewModel : BaseDataReviewItemViewModel
+    {
+        private StartPageDataReviewViewModel()
+        {
+            Content = typeof(Views.StartDataReviewView);
+        }
+        static StartPageDataReviewViewModel()
+        {
+
+        }
+        public static StartPageDataReviewViewModel Instance { get; } = new StartPageDataReviewViewModel();
+        public override MainPageType PageType =>  MainPageType.StartPage;
+    }
+}

+ 6 - 4
Avalonia/ShakerApp/ViewModels/DeviceManger/DeviceInfoViewModel.cs

@@ -21,9 +21,11 @@ namespace ShakerApp.ViewModels
         {
         }
 
-        public void SaveTdmsConfig(Dictionary<string, string> config)
+        public void SaveTdmsConfig(TDMS.ITDMSFile? config)
         {
-            if (config == null) config = new Dictionary<string, string>();
+            if (config == null) return;
+            var group = config.Contains(nameof(DeviceInfoModel)) ? config[nameof(DeviceInfoModel)]:config.AddGroup(nameof(DeviceInfoModel));
+            if (group == null) return;
             typeof(DeviceInfoModel).GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
                 .Select(x => (x, x.GetValue(Model)))
                 .ToList()
@@ -35,11 +37,11 @@ namespace ShakerApp.ViewModels
                     }
                     if (x.x.FieldType.IsAssignableTo(typeof(IList)) || x.x.FieldType.IsArray)
                     {
-                        config[$"{nameof(DeviceInfoModel)}_{x.x.Name}"] = string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}"));
+                        group.CreateOrUpdateProperty($"{x.x.Name}", string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}")));
                     }
                     else
                     {
-                        config[$"{nameof(DeviceInfoModel)}_{x.x.Name}"] = x.Item2?.ToString() ?? string.Empty;
+                        group.CreateOrUpdateProperty($"{x.x.Name}", x.Item2?.ToString() ?? string.Empty);
                     }
                 });
         }

+ 2 - 9
Avalonia/ShakerApp/ViewModels/Log/LogViewModel.cs

@@ -9,7 +9,6 @@ namespace ShakerApp.ViewModels
 {
     internal class LogViewModel:DisplayViewModelBase<IModel>
     {
-        private object locker = new object();
         public AvaloniaList<IndexValueItemViewModel<LogItemViewModel>> Logs { get; } = new AvaloniaList<IndexValueItemViewModel<LogItemViewModel>>();
         private LogViewModel()
         {
@@ -17,10 +16,7 @@ namespace ShakerApp.ViewModels
             Content = typeof(Views.LogsView);
             GetEvent<Models.LogItemModel>().Subscrip((sender, args) =>
             {
-                lock (locker)
-                {
-                    Tools.DispatherInovke.Inovke(()=> Logs.Add(new IndexValueItemViewModel<LogItemViewModel>(Logs.Count+1,new LogItemViewModel(args.Data.Message,args.Data.LogType))));
-                }
+                Tools.DispatherInovke.Inovke(() => Logs.Add(new IndexValueItemViewModel<LogItemViewModel>(Logs.Count + 1, new LogItemViewModel(args.Data.Message, args.Data.LogType))));
             });
             GetEvent(nameof(Models.LogItemModel)).Subscrip((sender, args) =>
             {
@@ -36,10 +32,7 @@ namespace ShakerApp.ViewModels
         }
         public void AddLog(string msg,LogType logType = LogType.Info)
         {
-            lock (locker)
-            {
-               Tools.DispatherInovke.Inovke(()=>  Logs.Add(new IndexValueItemViewModel<LogItemViewModel>(Logs.Count + 1, new LogItemViewModel(msg, logType))));
-            }
+            Tools.DispatherInovke.Inovke(() => Logs.Add(new IndexValueItemViewModel<LogItemViewModel>(Logs.Count + 1, new LogItemViewModel(msg, logType))));
         }
         public static LogViewModel Instance { get; } = new LogViewModel();
     }

+ 3 - 7
Avalonia/ShakerApp/ViewModels/MainPage/IMainPageViewModel.cs

@@ -1,6 +1,4 @@
-
-using ParquetSharp;
-using Shaker.Models;
+using Shaker.Models;
 using ShakerApp.Views;
 using System;
 using System.Collections.Generic;
@@ -14,12 +12,10 @@ namespace ShakerApp.ViewModels
     {
         public MainPageType PageType { get; }
 
-        public void UpdataColnumInfo();
         public void Start();
         public void Stop();
-        public Column[] Columns { get; }
         public void UpdateData(List<IResultDataModel> model);
-        public void SaveTdmsConfig(Dictionary<string,string> config);
-        public void SaveTestData(ParquetFileWriter file);
+        public void SaveTdmsConfig(TDMS.ITDMSFile? config);
+        public void SaveTestData(TDMS.ITDMSFile? file);
     }
 }

+ 4 - 5
Avalonia/ShakerApp/ViewModels/MainPage/MainPageViewModel.cs

@@ -1,5 +1,4 @@
 using Avalonia.Collections;
-using ParquetSharp;
 using Shaker.Models;
 using ShakerApp.Views;
 using System;
@@ -24,7 +23,6 @@ namespace ShakerApp.ViewModels
             RandomMainPageViewModel.Instance,
             OutSignalMainPageViewModel.Instance,
         };
-        public Column[] Columns => MainPage.Columns;
         private MainPageViewModel()
         {
             this.GetType().Assembly.GetTypes()
@@ -51,12 +49,13 @@ namespace ShakerApp.ViewModels
 
         }
 
-        public void SaveTdmsConfig(Dictionary<string, string> config)
+        public void SaveTdmsConfig(TDMS.ITDMSFile? config)
         {
+            if (config == null) return;
             MainPage.SaveTdmsConfig(config);
-            config[nameof(MainPageType)] = MainPageType.ToString();
+            config.CreateOrUpdateProperty(nameof(MainPageType), MainPageType.ToString());
         }
-        public void SaveTestData(ParquetFileWriter file)=>MainPage.SaveTestData(file);
+        public void SaveTestData(TDMS.ITDMSFile? file)=>MainPage.SaveTestData(file);
         public MainPageType MainPageType 
         {
             get => mainPageType;

+ 9 - 15
Avalonia/ShakerApp/ViewModels/MainPage/OutSignalMainPageViewModel.cs

@@ -1,6 +1,5 @@
 using Avalonia.Collections;
 using Avalonia.Controls;
-using ParquetSharp;
 using Shaker.Models;
 using ShakerApp.Models;
 using ShakerApp.Tools;
@@ -17,28 +16,23 @@ namespace ShakerApp.ViewModels
 {
     internal abstract class BaseMainPageViewModel<TModel>:DisplayViewModelBase<TModel>,IMainPageViewModel where TModel:IModel
     {
-        private protected Column[] columns = new Column[0];
+        public const string TimeDomainData = "TimeDomainData";
         public abstract MainPageType PageType { get; }
         public virtual void Start() { }
         public virtual void Stop() { }
-        public Column[] Columns => columns;
-        public virtual void UpdataColnumInfo()
+        public virtual void SaveTestData(TDMS.ITDMSFile? file)
         {
-            columns = new Column[ViewModels.ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Count];
-            for (int i = 0; i < columns.Length; i++)
-            {
-                columns[i] = new Column<double>($"{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Name}_{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Unit}_{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].AnalogType}_{Models.DataAxisType.Linear}");
-            }
-        }
-        public virtual void SaveTestData(ParquetFileWriter file)
-        {
-            var writer = file.AppendBufferedRowGroup();
+            if (file == null) return;
+            var group = file.Contains(TimeDomainData) ? file[TimeDomainData]:file.AddGroup(TimeDomainData);
+            if (group == null) return;
             for(int i=0;i<ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Count;i++)
             {
-                writer.Column(i).LogicalWriter<double>().WriteBatch(ShakerDataViewModel.Instance.GetAnalogRawData(i));
+                bool exit = group.Contains(ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Name);
+                var ch = exit ? group[ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Name] : group.AddChannel( TDMS.Common.TDMSDataType.Double,ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Name, ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Unit);
+                ch?.AppendData(ShakerDataViewModel.Instance.GetAnalogRawData(i));
             }
         }
-        public virtual void SaveTdmsConfig(Dictionary<string, string> config)
+        public virtual void SaveTdmsConfig(TDMS.ITDMSFile? config)
         {
             ShakerConfigViewModel.Instance.SaveTdmsConfig(config);
         }

+ 38 - 29
Avalonia/ShakerApp/ViewModels/MainPage/RandomMainPageViewModel.cs

@@ -4,7 +4,6 @@ using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
 using OxyPlot;
 using OxyPlot.Series;
-using ParquetSharp;
 using Shaker.Models;
 using ShakerApp.Tools;
 using ShakerApp.Views;
@@ -19,6 +18,7 @@ namespace ShakerApp.ViewModels
 {
     internal class RandomMainPageViewModel:BaseMainPageViewModel<RandomDataModel>
     {
+        public const string SpectrumData = "SpectrumData";
         [PropertyAssociation(nameof(RandomDataModel.CurrentIdentifyDisplacement))]
         public double CurrentIdentifyDisplacement => Model.CurrentIdentifyDisplacement;
         [PropertyAssociation(nameof(RandomDataModel.CurrentIdentifyRms))]
@@ -137,10 +137,13 @@ namespace ShakerApp.ViewModels
         {
 
         }
-        public override void SaveTdmsConfig(Dictionary<string, string> config)
+        public override void SaveTdmsConfig(TDMS.ITDMSFile? config)
         {
+            if (config == null) return;
             base.SaveTdmsConfig(config); 
-            typeof(RandomConfigViewModel).GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
+            var group = config.Contains(nameof(RandomConfigModel)) ? config[nameof(RandomConfigModel)]:config.AddGroup(nameof(RandomConfigModel));
+            if (group == null) return;
+            typeof(RandomConfigModel).GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
                 .Select(x => (x, x.GetValue(RandomConfigViewModel.Instance.Model)))
                 .ToList()
                 .ForEach(x =>
@@ -151,43 +154,42 @@ namespace ShakerApp.ViewModels
                     }
                     if (x.x.FieldType.IsAssignableTo(typeof(IList)) || x.x.FieldType.IsArray)
                     {
-                        config[$"{nameof(RandomConfigViewModel)}_{x.x.Name}"] = string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}"));
+                        group.CreateOrUpdateProperty($"{x.x.Name}", string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}")));
                     }
                     else
                     {
-                        config[$"{nameof(RandomConfigViewModel)}_{x.x.Name}"] = x.Item2?.ToString() ?? string.Empty;
+                        group.CreateOrUpdateProperty($"{x.x.Name}", x.Item2?.ToString() ?? string.Empty);
                     }
                 });
         }
-        public override void UpdataColnumInfo()
+        public override void SaveTestData(TDMS.ITDMSFile? file)
         {
-            /*
-             * 保存时域信号和各加速度通道psd数据、加速度合成PSD数据和驱动PSD数据
-             */
-            columns = new Column[ShakerConfigViewModel.Instance.ChannelCount + ShakerConfigViewModel.Instance.AccelerationSensorCount + 2];
-            for(int i=0;i<columns.Length;i++)
+            if (file == null) return;
+            base.SaveTestData(file);
+            var group = file.Contains(SpectrumData) ? file[SpectrumData] : file.AddGroup(SpectrumData);
+            if (group == null) return;
+            var acc = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Where(x => x.AnalogType == AnalogType.DivideAcceleration).ToArray();
+            if(acc.Length>0)
             {
-                if(i<ShakerConfigViewModel.Instance.ChannelCount)
-                {
-                    columns[i] = new Column<double>($"{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Name}_{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Unit}_{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].AnalogType}_{Models.DataAxisType.Linear}");
-                }
-                else
+                for(int i=0;i<acc.Length;i++)
                 {
-                    columns[i] = new Column<double>($"{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Name}_{App.Current?.FindResource("RandomValueUnit")}_{""}_{Models.DataAxisType.Logarithm}");
+                    var ch = group.Contains(acc[i].Name) ? group[acc[i].Name] : group.AddChannel(TDMS.Common.TDMSDataType.Double, acc[i].Name, App.Current?.FindResource("RandomValueUnit") + "");
+                    ch?.AppendData(Model.CurrentAccelerationPSD[i]);
                 }
             }
-        }
-        public override void SaveTestData(ParquetFileWriter file)
-        {
-            base.SaveTestData(file);
-            if (lastdata == null) return;
-            var writer = file.AppendBufferedRowGroup();
-            for(int i=0;i<ShakerConfigViewModel.Instance.AccelerationSensorCount;i++)
+
             {
-                writer.Column(ShakerConfigViewModel.Instance.AnalogSignals.Count + i).LogicalWriter<double>().WriteBatch(lastdata.CurrentAccelerationPSD[i]);
+                var ch = group.Contains("AccelerationSpectrum") ? group["AccelerationSpectrum"] : group.AddChannel(TDMS.Common.TDMSDataType.Double, "AccelerationSpectrum", App.Current?.FindResource("RandomValueUnit") + "");
+                ch?.AppendData(Model.CurrentAccelerationSynthesisPSD);
+            }
+            {
+                var dr = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.FirstOrDefault(x => x.AnalogType == AnalogType.GivenDriver);
+                if (dr != null)
+                {
+                    var ch = group.Contains(dr.Name) ? group[dr.Name] : group.AddChannel(TDMS.Common.TDMSDataType.Double, dr.Name, App.Current?.FindResource("RandomValueUnit") + "");
+                    ch?.AppendData(Model.DriverPSD);
+                }
             }
-            writer.Column(ShakerConfigViewModel.Instance.AccelerationSensorCount + ShakerConfigViewModel.Instance.AnalogSignals.Count).LogicalWriter<double>().WriteBatch(lastdata.CurrentAccelerationSynthesisPSD);
-            writer.Column(ShakerConfigViewModel.Instance.AccelerationSensorCount + ShakerConfigViewModel.Instance.Accelerations.Count + 1).LogicalWriter<double>().WriteBatch(lastdata.DriverPSD);
         }
         public override void Start()
         {
@@ -197,10 +199,8 @@ namespace ShakerApp.ViewModels
         public override void Stop()
         {
         }
-        private RandomDataModel lastdata;
         public override void UpDateModel(RandomDataModel model)
         {
-            lastdata = model;
             base.UpDateModel(model);
             int startindex = (int)(RandomConfigViewModel.Instance.MinFrequency / RandomConfigViewModel.Instance.FrequencyResolution);
             for(int i=0;i<datas.Count;i++)
@@ -214,8 +214,17 @@ namespace ShakerApp.ViewModels
                 LineSeries[i].ItemsSource = datas;
             }
             PlotModel.InvalidatePlot(true);
+            SaveSpectrumData();
         }
 
+        private void SaveSpectrumData()
+        {
+            var file = ViewModels.ShakerDataViewModel.Instance.File;
+            if (file == null) return;
+            var group= file.Contains(SpectrumData) ? file[SpectrumData]:file.AddGroup(SpectrumData);
+            if (group == null) return;
+
+        }
         public override void UpdateData(List<IResultDataModel> model)
         {
             if(model !=null &&model.Count >0 && model.First() is RandomDataModel randomdata)

+ 25 - 22
Avalonia/ShakerApp/ViewModels/MainPage/SineMainPageViewModel.cs

@@ -2,7 +2,6 @@
 using Avalonia.Controls;
 using OxyPlot;
 using OxyPlot.Series;
-using ParquetSharp;
 using Shaker.Models;
 using Shaker.Models.Tools;
 using ShakerApp.Tools;
@@ -20,7 +19,6 @@ namespace ShakerApp.ViewModels
 {
     internal class SineMainPageViewModel : BaseMainPageViewModel<SineDataModel>
     {
-        public const string TDMSConfigName = "SweepConfig";
         public const string TDMSDataName = "SweepData";
         List<OxyColor> oxyColors = new List<OxyColor>() {OxyColors.Black, OxyColors.Green, OxyColors.Red, OxyColors.Red, OxyColors.Yellow, OxyColors.Yellow };
         List<LineStyle> lineStyles = new List<LineStyle>() {LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.LongDashDotDot, LineStyle.LongDashDotDot };
@@ -106,20 +104,12 @@ namespace ShakerApp.ViewModels
         {
 
         }
-        public override void UpdataColnumInfo()
-        {
-            columns = new Column[ViewModels.ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Count+3];
-            for (int i = 0; i < ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Count; i++)
-            {
-                 columns[i] = new Column<double>($"{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Name}_{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Unit}_{ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].AnalogType}_{Models.DataAxisType.Linear}");
-            }
-            columns[^3] = new Column<double>($"Acceleration_g_{" "}_{Models.DataAxisType.Logarithm}");
-            columns[^2] = new Column<double>($"Frequency_g_{" "}_{Models.DataAxisType.Logarithm}");
-            columns[^1] = new Column<uint>($"SweepIndex_ _{" "}_{Models.DataAxisType.Logarithm}");
-        }
-        public override void SaveTdmsConfig(Dictionary<string, string> config)
+        public override void SaveTdmsConfig(TDMS.ITDMSFile? config)
         {
+            if (config == null) return;
             base.SaveTdmsConfig(config);
+            var group = config.Contains(nameof(SweepConfigModel)) ? config[nameof(SweepConfigModel)]:config.AddGroup(nameof(SweepConfigModel));
+            if (group == null) return;
             typeof(SweepConfigModel) .GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
                 .Select(x => (x, x.GetValue(SweepConfigViewModel.Instance.Model)))
                 .ToList()
@@ -131,11 +121,11 @@ namespace ShakerApp.ViewModels
                     }
                     if (x.x.FieldType.IsAssignableTo(typeof(IList)) || x.x.FieldType.IsArray)
                     {
-                        config[$"{nameof(SweepConfigModel)}_{x.x.Name}"]  = string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}"));
+                        group.CreateOrUpdateProperty($"{x.x.Name}", string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}")));
                     }
                     else
                     {
-                        config[$"{nameof(SweepConfigModel)}_{x.x.Name}"] = x.Item2?.ToString() ?? string.Empty;
+                        group.CreateOrUpdateProperty($"{x.x.Name}", x.Item2?.ToString() ?? string.Empty);
                     }
                 });
         }
@@ -255,19 +245,32 @@ namespace ShakerApp.ViewModels
                 SweepConfigViewModel.Instance.Model.CalcAmpt(sine.CurrentFrequency, ref value, ref upstop, ref upwarn, ref downstop, ref downwarn);
                 datas.Insert(index + 1, new SweepData(sine.CurrentFrequency,currentacc, value,  upstop, downstop, upwarn, downwarn));
             });
-            var file = ShakerDataViewModel.Instance.Writer;
+            var file = ShakerDataViewModel.Instance.File;
             if (file == null) return;
             var savemodels = models.DistinctBy(x => x.CurrentFrequency).Where(x=>x.CurrentFrequency!=lastwritefreq).ToList();
             if (savemodels.Count == 0) return;
             lastwritefreq = savemodels[^1].CurrentFrequency;
             try
             {
-                var writer = file.AppendBufferedRowGroup();
-                writer.Column(ShakerConfigViewModel.Instance.AccelerationSensorCount).LogicalWriter<double>().WriteBatch(savemodels.Select(x => x.CurrentAcceleration).ToArray());
-                writer.Column(ShakerConfigViewModel.Instance.AccelerationSensorCount + 1).LogicalWriter<double>().WriteBatch(savemodels.Select(x => x.CurrentFrequency).ToArray());
-                writer.Column(ShakerConfigViewModel.Instance.AccelerationSensorCount + 2).LogicalWriter<uint>().WriteBatch(savemodels.Select(x => x.SweepIndex).ToArray());
+                var group= file.Contains(TDMSDataName) ? file[TDMSDataName]:file.AddGroup(TDMSDataName);
+                if (group == null) return;
+                var ch = group.Contains(nameof(SineDataModel.CurrentFrequency)) ? group[nameof(SineDataModel.CurrentFrequency)] : group.AddChannel(TDMS.Common.TDMSDataType.Double, nameof(SineDataModel.CurrentFrequency), "Hz");
+                if (ch != null)
+                {
+                    ch.AppendData(savemodels.Select(x => x.CurrentFrequency).ToArray());
+                }
+                ch = group.Contains(nameof(SineDataModel.CurrentAcceleration)) ? group[nameof(SineDataModel.CurrentAcceleration)] : group.AddChannel(TDMS.Common.TDMSDataType.Double,nameof(SineDataModel.CurrentAcceleration), "g");
+                if (ch != null)
+                {
+                    ch.AppendData(savemodels.Select(x => x.CurrentAcceleration).ToArray());
+                }
+                ch = group.Contains(nameof(SineDataModel.SweepIndex)) ? group[nameof(SineDataModel.SweepIndex)] : group.AddChannel(TDMS.Common.TDMSDataType.Int32, nameof(SineDataModel.SweepIndex), "");
+                if (ch != null)
+                {
+                    ch.AppendData(savemodels.Select(x => (int)x.SweepIndex).ToArray());
+                }
             }
-            catch
+            catch(Exception ex)
             {
 
             }

+ 27 - 9
Avalonia/ShakerApp/ViewModels/MainViewModel.cs

@@ -18,6 +18,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
 using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
 using System.Windows.Input;
 
 namespace ShakerApp.ViewModels;
@@ -43,7 +44,18 @@ public class MainViewModel : DisplayViewModelBase<IModel>
         {
             OnPropertyChanged(nameof(Title));
             OnPropertyChanged(nameof(TitleColor));
+            CommunicationViewModel.Instance.ServiceCommunication?.GetEvent(Topic.DisConnect)?.Publish(this);
         });
+        CommunicationViewModel.Instance.PropertyChanged += (sender, args) =>
+        {
+            switch (args.PropertyName)
+            {
+                case nameof(CommunicationViewModel.LocalIsConnect):
+                    OnPropertyChanged(nameof(TitleColor));
+                    OnPropertyChanged(nameof(Title));
+                    break;
+            }
+        };
         MainPageViewModel.Instance.PropertyChanged += (sender, args) =>
         {
             switch(args.PropertyName)
@@ -53,10 +65,6 @@ public class MainViewModel : DisplayViewModelBase<IModel>
                     break;
             }
         };
-        GetEvent(Topic.DisConnect).Subscrip((sender, args) =>
-        {
-            CommunicationViewModel.Instance.ServiceCommunication?.GetEvent(Topic.DisConnect)?.Publish(this);
-        });
         this.GetType().Assembly.GetTypes()
             .Where(x => x.IsAnsiClass && !x.IsAbstract && x.IsAssignableTo(typeof(ObservableObject)))
             .ToList()
@@ -84,7 +92,7 @@ public class MainViewModel : DisplayViewModelBase<IModel>
     {
 
     }
-    public Avalonia.Media.IBrush TitleColor => CommunicationViewModel.Instance.LocalIsConnect ? Brushes.Black : Brushes.Red;
+    public Avalonia.Media.IBrush TitleColor => CommunicationViewModel.Instance.LocalIsConnect ? Brushes.Black : Brushes.Black;
     public ICommand ExitCommand => new RelayCommand(()=>Exit(""));
     [MenuClick("MenuExit")]
     private void Exit(string? p)
@@ -115,6 +123,20 @@ public class MainViewModel : DisplayViewModelBase<IModel>
         }
         return s;
     }
+
+    public ICommand DataReviewCommand =>new RelayCommand<string>(DataReview);
+    private async void DataReview(string? p)
+    {
+        if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop && !string.IsNullOrEmpty(p))
+        {
+            SelectTestDataViewModel.Instance.InitData();
+            SelectTestDataViewModel.Instance.Title = p;
+            BaseDialogWindow window = new BaseDialogWindow();
+            window.DataContext = SelectTestDataViewModel.Instance;
+            DeviceMangerViewModel.Instance.CloseWindowAction = () => window?.Close();
+            await window.ShowDialog(desktop.MainWindow!);
+        }
+    }
     public ICommand ConnectCommand => new RelayCommand(Connect);
     private void Connect()
     {
@@ -614,10 +636,6 @@ public class MainViewModel : DisplayViewModelBase<IModel>
         OnPropertyChanged(nameof(Title));
         OnPropertyChanged(nameof(TitleColor));
         CommunicationViewModel.Instance.ServiceCommunication?.GetEvent<DeviceInfoModel?>()?.Publish(this, DeviceMangerViewModel.Instance.CurrentDevice?.Model);
-        foreach (var item in MainPageViewModel.Instance.MainPageViewModels)
-        {
-            item.UpdataColnumInfo();
-        }
 
     }
     public static MainViewModel Default { get; } = new MainViewModel();

+ 9 - 0
Avalonia/ShakerApp/ViewModels/Menu/MenuViewModel.cs

@@ -54,6 +54,7 @@ namespace ShakerApp.ViewModels
         {
             Menus.Add(GetFileMenu());
             Menus.Add(GetDeviceMenu());
+            Menus.Add(GetTestMenu());
         }
         private MenuItemViewModel GetFileMenu()
         {
@@ -140,6 +141,14 @@ namespace ShakerApp.ViewModels
                 Header = "MenuDevice",
             };
         }
+        private MenuItemViewModel GetTestMenu()
+        {
+            return new MenuItemViewModel(new MenuItemViewModel())
+            {
+                Header = "MenuTest",
+                IsEnabled = false,
+            };
+        }
         static MenuViewModel()
         {
 

+ 6 - 5
Avalonia/ShakerApp/ViewModels/ShakerConfig/ShakerConfigViewModel.cs

@@ -1,7 +1,6 @@
 using Avalonia.Collections;
 using Avalonia.Controls;
 using Avalonia.Markup.Xaml.MarkupExtensions;
-using ParquetSharp;
 using Shaker.Models;
 using ShakerApp.Tools;
 using System;
@@ -128,9 +127,11 @@ namespace ShakerApp.ViewModels
         {
 
         }
-        public void SaveTdmsConfig(Dictionary<string,string> config)
+        public void SaveTdmsConfig(TDMS.ITDMSFile? config)
         {
-            if (config == null) config = new Dictionary<string, string>();
+            if (config == null) return;
+            var group = config.Contains(nameof(ShakerConfigModel)) ? config[nameof(ShakerConfigModel)]:config.AddGroup(nameof(ShakerConfigModel));
+            if (group == null) return;
             typeof(ShakerConfigModel).GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
                 .Select(x =>(x, x.GetValue(Model)))
                 .ToList()
@@ -142,11 +143,11 @@ namespace ShakerApp.ViewModels
                     }
                     if(x.x.FieldType.IsAssignableTo(typeof(IList)) || x.x.FieldType.IsArray)
                     {
-                        config[$"{nameof(ShakerConfigModel)}_{x.x.Name}"] = string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}")); 
+                        group.CreateOrUpdateProperty($"{x.x.Name}", string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}"))); 
                     }
                     else
                     {
-                        config[$"{nameof(ShakerConfigModel)}_{x.x.Name}"] = x.Item2?.ToString() ?? string.Empty;
+                        group.CreateOrUpdateProperty($"{x.x.Name}", x.Item2?.ToString() ?? string.Empty);
                     }
                 });
         }

+ 7 - 7
Avalonia/ShakerApp/ViewModels/ShakerControl/ShakerControlViewModel.cs

@@ -1,5 +1,4 @@
-using ParquetSharp;
-using Shaker.Models;
+using Shaker.Models;
 using ShakerApp.Tools;
 using System;
 using System.Collections;
@@ -14,7 +13,6 @@ namespace ShakerApp.ViewModels
 {
     public class ShakerControlViewModel : DisplayViewModelBase<ShakerControlModel>
     {
-        public const string TDMSConfigName = "ShakerControl";
         public override bool CanResize => false;
         public override double Width => 960;
         public override double Height => 560;
@@ -23,9 +21,11 @@ namespace ShakerApp.ViewModels
         {
 
         }
-        public void SaveTdmsConfig(Dictionary<string,string> config)
+        public void SaveTdmsConfig(TDMS.ITDMSFile? config)
         {
-            if (config == null) config = new Dictionary<string, string>();
+            if (config == null) return;
+            var group=config.Contains(nameof(ShakerControlModel)) ? config[nameof(ShakerControlModel)]:config.AddGroup(nameof(ShakerControlModel));
+            if (group == null) return;
             typeof(ShakerControlModel).GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
                 .Select(x => (x, x.GetValue(Model)))
                 .ToList()
@@ -37,11 +37,11 @@ namespace ShakerApp.ViewModels
                     }
                     if (x.x.FieldType.IsAssignableTo(typeof(IList)) || x.x.FieldType.IsArray)
                     {
-                        config[$"{nameof(ShakerControlModel)}_{x.x.Name}"] = string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}"));
+                        group.CreateOrUpdateProperty($"{x.x.Name}",string.Join("", x.Item2.GetBytes().Select(x => $"{x:X2}")));
                     }
                     else
                     {
-                        config[$"{nameof(ShakerControlModel)}_{x.x.Name}"] = x.Item2?.ToString() ?? string.Empty;
+                        group.CreateOrUpdateProperty($"{x.x.Name}", x.Item2?.ToString() ?? string.Empty);
                     }
                 });
         }

+ 9 - 7
Avalonia/ShakerApp/ViewModels/ShakerDataViewModel.cs

@@ -8,15 +8,14 @@ using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Text;
 using System.Threading.Tasks;
-using ParquetSharp;
 
 namespace ShakerApp.ViewModels
 {
     internal class ShakerDataViewModel:DisplayViewModelBase<IModel>
     {
-        public ParquetSharp.ParquetFileWriter Writer => tdmsfile;
+        public TDMS.ITDMSFile File => tdmsfile;
         [AllowNull]
-        private ParquetFileWriter tdmsfile;
+        private TDMS.ITDMSFile tdmsfile;
         private object _datalocker = new object();
         private Dictionary<Shaker.Models.AnalogType, List<(List<DataPoint>,Models.StatisticsModel)>> AnalogDataCache = new Dictionary<AnalogType, List<(List<DataPoint>, Models.StatisticsModel)>>();
         private ShakerDataViewModel()
@@ -42,17 +41,19 @@ namespace ShakerApp.ViewModels
                     {
                         if (tdmsfile == null)
                         {
+                            tdmsfile = TDMS.TDMSDataBuilder.BuildNew(System.IO.Path.Combine(ViewModels.ShakerSettingViewModel.Instance.DataDirectory, $"{DateTime.Now:yyyy-MM-dd HH-mm-ss}.tdms"),"Data");
                             Dictionary<string, string> config = new Dictionary<string, string>();
-                            ShakerControlViewModel.Instance.SaveTdmsConfig(config);
-                            MainPageViewModel.Instance.SaveTdmsConfig(config);
-                            DeviceMangerViewModel.Instance.CurrentDevice?.SaveTdmsConfig(config);
-                            tdmsfile = new ParquetFileWriter(System.IO.Path.Combine(ViewModels.ShakerSettingViewModel.Instance.DataDirectory, $"{DateTime.Now:yyyy-MM-dd HH-mm-ss}.dat"),MainPageViewModel.Instance.MainPage.Columns, Compression.Uncompressed,config);
+                            ShakerControlViewModel.Instance.SaveTdmsConfig(tdmsfile);
+                            MainPageViewModel.Instance.SaveTdmsConfig(tdmsfile);
+                            DeviceMangerViewModel.Instance.CurrentDevice?.SaveTdmsConfig(tdmsfile);
                         }
                     }
                     break;
                 default:
                     if (tdmsfile != null)
                     {
+                        tdmsfile.Save();
+                        tdmsfile.Close();
                         tdmsfile.Dispose();
                         tdmsfile = null;
                     }
@@ -62,6 +63,7 @@ namespace ShakerApp.ViewModels
             if (ShakerStatusViewModel.Instance.RTStatus == RTStatus.SignalGen && tdmsfile != null)
             {
                 MainPageViewModel.Instance.SaveTestData(tdmsfile);
+                tdmsfile.Save();
             }
             CommunicationViewModel.Instance.ServiceCommunication?.GetEvent(Topic.DATA)?.Publish(this, null);
         }

+ 0 - 1
Avalonia/ShakerApp/ViewModels/ViewModelBase.cs

@@ -4,7 +4,6 @@ using Avalonia.Threading;
 using CommunityToolkit.Mvvm.ComponentModel;
 using CommunityToolkit.Mvvm.Input;
 using EventBus;
-using Mono.CompilerServices.SymbolWriter;
 using Shaker.Models;
 using SukiUI.Dialogs;
 using SukiUI.Toasts;

+ 56 - 0
Avalonia/ShakerApp/Views/DataReview/LoadTestDataView.axaml

@@ -0,0 +1,56 @@
+<UserControl
+    x:Class="ShakerApp.Views.LoadTestDataView"
+    xmlns="https://github.com/avaloniaui"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:vm="using:ShakerApp.ViewModels"
+    Width="{Binding Width}"
+    Height="{Binding Height}"
+    d:DesignHeight="450"
+    d:DesignWidth="800"
+    x:DataType="vm:SelectTestDataViewModel"
+    DataContext="{Binding Source={x:Static vm:SelectTestDataViewModel.Instance}}"
+    mc:Ignorable="d">
+    <StackPanel
+        Height="{StaticResource ItemHeight}"
+        HorizontalAlignment="Center"
+        Orientation="Horizontal">
+        <TextBlock VerticalAlignment="Center" Text="{DynamicResource MenuFile}" />
+
+        <Border
+            Width="420"
+            Margin="4,0,0,0"
+            Background="Transparent"
+            BorderThickness="1"
+            CornerRadius="6"
+            Cursor="Hand">
+            <TextBlock
+                Margin="10,4,10,4"
+                VerticalAlignment="Center"
+                Text="{Binding SelectedFile}" />
+            <Interaction.Behaviors>
+                <EventTriggerBehavior EventName="PointerReleased">
+                    <InvokeCommandAction Command="{Binding SelectFileCommand}" CommandParameter="MenuFile" />
+                </EventTriggerBehavior>
+            </Interaction.Behaviors>
+            <Border.Styles>
+                <Style Selector="Border">
+                    <Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderHighBrush}" />
+                </Style>
+                <Style Selector="Border:pointerover">
+                    <Setter Property="BorderBrush" Value="{DynamicResource ThemeAccentBrush}" />
+                </Style>
+            </Border.Styles>
+        </Border>
+        <Button
+            Width="{StaticResource ItemHeight}"
+            Height="{StaticResource ItemHeight}"
+            Margin="4,0,0,0"
+            Padding="0,8,0,8"
+            Command="{Binding SelectFileCommand}"
+            CommandParameter="MenuFile">
+            <PathIcon Data="{StaticResource SelectFileGeometry}" />
+        </Button>
+    </StackPanel>
+</UserControl>

+ 13 - 0
Avalonia/ShakerApp/Views/DataReview/LoadTestDataView.axaml.cs

@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace ShakerApp.Views;
+
+public partial class LoadTestDataView : UserControl
+{
+    public LoadTestDataView()
+    {
+        InitializeComponent();
+    }
+}

+ 11 - 0
Avalonia/ShakerApp/Views/DataReview/OutSignalDataReviewView.axaml

@@ -0,0 +1,11 @@
+<UserControl
+    x:Class="ShakerApp.Views.OutSignalDataReviewView"
+    xmlns="https://github.com/avaloniaui"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    d:DesignHeight="450"
+    d:DesignWidth="800"
+    mc:Ignorable="d">
+    Welcome to Avalonia!
+</UserControl>

+ 13 - 0
Avalonia/ShakerApp/Views/DataReview/OutSignalDataReviewView.axaml.cs

@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace ShakerApp.Views;
+
+public partial class OutSignalDataReviewView : UserControl
+{
+    public OutSignalDataReviewView()
+    {
+        InitializeComponent();
+    }
+}

+ 8 - 0
Avalonia/ShakerApp/Views/DataReview/RandomDataReviewView.axaml

@@ -0,0 +1,8 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="ShakerApp.Views.RandomDataReviewView">
+  Welcome to Avalonia!
+</UserControl>

+ 13 - 0
Avalonia/ShakerApp/Views/DataReview/RandomDataReviewView.axaml.cs

@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace ShakerApp.Views;
+
+public partial class RandomDataReviewView : UserControl
+{
+    public RandomDataReviewView()
+    {
+        InitializeComponent();
+    }
+}

+ 8 - 0
Avalonia/ShakerApp/Views/DataReview/SineDataReviewView.axaml

@@ -0,0 +1,8 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="ShakerApp.Views.SineDataReviewView">
+  Welcome to Avalonia!
+</UserControl>

+ 13 - 0
Avalonia/ShakerApp/Views/DataReview/SineDataReviewView.axaml.cs

@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace ShakerApp.Views;
+
+public partial class SineDataReviewView : UserControl
+{
+    public SineDataReviewView()
+    {
+        InitializeComponent();
+    }
+}

+ 11 - 0
Avalonia/ShakerApp/Views/DataReview/StartDataReviewView.axaml

@@ -0,0 +1,11 @@
+<UserControl
+    x:Class="ShakerApp.Views.StartDataReviewView"
+    xmlns="https://github.com/avaloniaui"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    d:DesignHeight="450"
+    d:DesignWidth="800"
+    mc:Ignorable="d">
+    Welcome to Avalonia!
+</UserControl>

+ 13 - 0
Avalonia/ShakerApp/Views/DataReview/StartDataReviewView.axaml.cs

@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace ShakerApp.Views;
+
+public partial class StartDataReviewView : UserControl
+{
+    public StartDataReviewView()
+    {
+        InitializeComponent();
+    }
+}

+ 1 - 1
Avalonia/ShakerApp/Views/File/LoadConfigView.axaml

@@ -50,7 +50,7 @@
             Padding="0,8,0,8"
             Command="{Binding SelectFileCommand}"
             CommandParameter="MenuFile">
-            <PathIcon Data="{StaticResource DataDirectoryGeometry}" />
+            <PathIcon Data="{StaticResource SelectFileGeometry}" />
         </Button>
     </StackPanel>
 </UserControl>

+ 1 - 1
Avalonia/ShakerApp/Views/File/SaveConfigView.axaml

@@ -50,7 +50,7 @@
             Padding="0,8,0,8"
             Command="{Binding SelectFileCommand}"
             CommandParameter="MenuFile">
-            <PathIcon Data="{StaticResource DataDirectoryGeometry}" />
+            <PathIcon Data="{StaticResource SelectFileGeometry}" />
         </Button>
 
 

+ 9 - 0
Avalonia/ShakerApp/Views/MainWindow.axaml

@@ -42,6 +42,15 @@
                     <PathIcon Data="{StaticResource OpenGeometry}" />
                 </MenuItem.Icon>
             </MenuItem>
+            <Separator />
+            <MenuItem
+                Command="{Binding DataReviewCommand}"
+                CommandParameter="MenuDataReview"
+                Header="{DynamicResource MenuDataReview}">
+                <MenuItem.Icon>
+                    <PathIcon Data="{StaticResource WaveGeometry}" />
+                </MenuItem.Icon>
+            </MenuItem>
 
             <Separator />
             <MenuItem Command="{Binding ExitCommand}" Header="{DynamicResource MenuExit}">

+ 4 - 5
Avalonia/SukiUI/SukiUI.csproj

@@ -28,11 +28,10 @@
 	</PropertyGroup>
 
 	<ItemGroup>
-		<PackageReference Include="Avalonia" Version="11.2.2" />
-		<PackageReference Include="Avalonia.Skia" Version="11.2.2" />
-		<PackageReference Include="SkiaSharp" Version="2.88.9" />
-		<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.2" />
-		<PackageReference Include="Avalonia.Themes.Simple" Version="11.2.2" />
+		<PackageReference Include="Avalonia" Version="11.2.3" />
+		<PackageReference Include="Avalonia.Skia" Version="11.2.3" />
+		<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.3" />
+		<PackageReference Include="Avalonia.Themes.Simple" Version="11.2.3" />
 	</ItemGroup>
 
 	<ItemGroup>

+ 0 - 29
Avalonia/Xaml.Behaviors/Xaml.Behaviors.csproj

@@ -1,29 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
-    <IncludeBuildOutput>False</IncludeBuildOutput>
-    <Nullable>enable</Nullable>
-    <NoWarn>$(NoWarn);NU5128</NoWarn>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Xaml.Behaviors</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" />
-  </ItemGroup>
-
-  <Import Project="..\..\build\SignAssembly.props" />
-  <Import Project="..\..\build\SourceLink.props" />
-  <Import Project="..\..\build\TrimmingEnable.targets" />
-
-  <ItemGroup>
-    <ProjectReference Include="..\Xaml.Interactivity\Xaml.Interactivity.csproj" />
-    <ProjectReference Include="..\Xaml.Interactions\Xaml.Interactions.csproj" />
-  </ItemGroup>
-
-</Project>

+ 0 - 12
Avalonia/Xaml.Interactions/Properties/AssemblyInfo.cs

@@ -1,12 +0,0 @@
-using System.Runtime.CompilerServices;
-using Avalonia.Metadata;
-
-[assembly: InternalsVisibleTo("Avalonia.Xaml.Interactions.UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001002940ed211918fcf63c506fad1d3f7f958b21ff8f06fd2089398296173f9ca93a69b9b380a828bf13fa80d1745beeb917ec3692f4d10e44b4c941619fc7bbd5052b26880697e6fa3f0ce322c4fa902d20b67a48b4144371218f6d39ad39145ea1fe5484052dd51a2ee62af3acd0759bcf92aaefec03978ded3cfaa84798e92de8")]
-
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions")]
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Core")]
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Custom")]
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.DragAndDrop")]
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Draggable")]
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Events")]
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Xaml.Interactions.Responsive")]

+ 0 - 50
Avalonia/Xaml.Interactions/Xaml.Interactions.csproj

@@ -1,50 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-    <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
-    <EnableDefaultItems>False</EnableDefaultItems>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Xaml.Interactions</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" />
-    <PackageReference Include="System.Reactive" />
-  </ItemGroup>
-
-  <PropertyGroup>
-    <InteractionsSourcesBasePath>..\Avalonia.Xaml.Interactions</InteractionsSourcesBasePath>
-    <InteractionsCustomSourcesBasePath>..\Avalonia.Xaml.Interactions.Custom</InteractionsCustomSourcesBasePath>
-    <InteractionsDragAndDropSourcesBasePath>..\Avalonia.Xaml.Interactions.DragAndDrop</InteractionsDragAndDropSourcesBasePath>
-    <InteractionsDraggableSourcesBasePath>..\Avalonia.Xaml.Interactions.Draggable</InteractionsDraggableSourcesBasePath>
-    <InteractionsEventsSourcesBasePath>..\Avalonia.Xaml.Interactions.Events</InteractionsEventsSourcesBasePath>
-    <InteractionsResponsiveSourcesBasePath>..\Avalonia.Xaml.Interactions.Responsive</InteractionsResponsiveSourcesBasePath>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <Compile Include="**\*.cs" Exclude="bin\**;obj\**" />
-    <Compile Include="$(InteractionsSourcesBasePath)\**\*.cs" Exclude="$(InteractionsSourcesBasePath)\Properties\**;$(InteractionsSourcesBasePath)\obj\**;$(InteractionsSourcesBasePath)\bin\**" />
-    <Compile Include="$(InteractionsCustomSourcesBasePath)\**\*.cs" LinkBase="Custom" Exclude="$(InteractionsCustomSourcesBasePath)\Properties\**;$(InteractionsCustomSourcesBasePath)\obj\**;$(InteractionsCustomSourcesBasePath)\bin\**" />
-    <Compile Include="$(InteractionsDragAndDropSourcesBasePath)\**\*.cs" LinkBase="DragAndDrop" Exclude="$(InteractionsDragAndDropSourcesBasePath)\Properties\**;$(InteractionsDragAndDropSourcesBasePath)\obj\**;$(InteractionsDragAndDropSourcesBasePath)\bin\**" />
-    <Compile Include="$(InteractionsDraggableSourcesBasePath)\**\*.cs" LinkBase="Draggable" Exclude="$(InteractionsDraggableSourcesBasePath)\Properties\**;$(InteractionsDraggableSourcesBasePath)\obj\**;$(InteractionsDraggableSourcesBasePath)\bin\**" />
-    <Compile Include="$(InteractionsEventsSourcesBasePath)\**\*.cs" LinkBase="Events" Exclude="$(InteractionsEventsSourcesBasePath)\Properties\**;$(InteractionsEventsSourcesBasePath)\obj\**;$(InteractionsEventsSourcesBasePath)\bin\**" />
-    <Compile Include="$(InteractionsResponsiveSourcesBasePath)\**\*.cs" LinkBase="Responsive" Exclude="$(InteractionsResponsiveSourcesBasePath)\Properties\**;$(InteractionsResponsiveSourcesBasePath)\obj\**;$(InteractionsResponsiveSourcesBasePath)\bin\**" />
-  </ItemGroup>
-
-  <Import Project="..\..\build\SignAssembly.props" />
-  <Import Project="..\..\build\SourceLink.props" />
-  <Import Project="..\..\build\TrimmingEnable.targets" />
-
-  <ItemGroup>
-    <ProjectReference Include="..\Xaml.Interactivity\Xaml.Interactivity.csproj" />
-  </ItemGroup>
-
-</Project>

+ 0 - 35
Avalonia/Xaml.Interactivity/Xaml.Interactivity.csproj

@@ -1,35 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
-    <OutputType>Library</OutputType>
-    <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
-    <Nullable>enable</Nullable>
-    <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
-    <EnableDefaultItems>False</EnableDefaultItems>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <PackageId>Xaml.Interactivity</PackageId>
-    <Description>Easily add interactivity to your Avalonia apps using XAML Behaviors. Behaviors encapsulate reusable functionalities for elements that can be easily added to your XAML without the need for more imperative code.</Description>
-    <PackageTags>Avalonia;Behavior;Action;Behaviors;Actions;Managed;C#;Interaction;Interactivity;Interactions;Xaml</PackageTags>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" />
-  </ItemGroup>
-
-  <PropertyGroup>
-    <SourcesBasePath>..\Avalonia.Xaml.Interactivity</SourcesBasePath>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <Compile Include="**\*.cs" Exclude="bin\**;obj\**" />
-    <Compile Include="$(SourcesBasePath)\**\*.cs" Exclude="$(SourcesBasePath)\obj\**;$(SourcesBasePath)\bin\**" />
-  </ItemGroup>
-
-  <Import Project="..\..\build\SignAssembly.props" />
-  <Import Project="..\..\build\SourceLink.props" />
-  <Import Project="..\..\build\TrimmingEnable.targets" />
-
-</Project>

+ 3 - 3
Communication/ActiveMQ/EasyMQ.MessagePackSerializer/EasyMQ.MessagePackSerializer.csproj

@@ -8,9 +8,9 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="MessagePack" Version="3.0.308" />
-    <PackageReference Include="MessagePack.Annotations" Version="3.0.308" />
-    <PackageReference Include="MessagePackAnalyzer" Version="3.0.308">
+    <PackageReference Include="MessagePack" Version="3.1.3" />
+    <PackageReference Include="MessagePack.Annotations" Version="3.1.3" />
+    <PackageReference Include="MessagePackAnalyzer" Version="3.1.3">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>

+ 6 - 1
Communication/ActiveMQCommunication/ActiveMQCommunication.csproj

@@ -15,7 +15,12 @@
     <Exec Command="xcopy /Y /E &quot;$(TargetDir)&quot; &quot;$(SolutionDir)Avalonia\ShakerApp\bin\$(Configuration)\net8.0\Communication\$(ProjectName)\&quot;" />
   </Target>
   <ItemGroup>
-    <PackageReference Include="MessagePack" Version="3.0.308" />
+    <PackageReference Include="MessagePack" Version="3.1.3" />
+    <PackageReference Include="MessagePack.Annotations" Version="3.1.3" />
+    <PackageReference Include="MessagePackAnalyzer" Version="3.1.3">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
   </ItemGroup>
 
   <ItemGroup>

+ 6 - 1
Communication/LocalCommunication/LocalCommunication.csproj

@@ -7,7 +7,12 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="MessagePack" Version="3.0.308" />
+    <PackageReference Include="MessagePack" Version="3.1.3" />
+    <PackageReference Include="MessagePack.Annotations" Version="3.1.3" />
+    <PackageReference Include="MessagePackAnalyzer" Version="3.1.3">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
   </ItemGroup>
   <Target Name="PostBuild" AfterTargets="PostBuildEvent">
     <Exec Command="xcopy /Y /E &quot;$(TargetDir)&quot; &quot;$(SolutionDir)Avalonia\ShakerApp\bin\$(Configuration)\net8.0\Communication\$(ProjectName)\&quot;" />

+ 0 - 311
Communication/NetMQ/AsyncReceiveExtensions.cs

@@ -1,311 +0,0 @@
-#if NETSTANDARD2_0 || NETSTANDARD2_1 || NET47
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace NetMQ
-{
-    /// <summary>
-    /// Provides extension methods for the <see cref="NetMQSocket"/>,
-    /// via which messages may be received asynchronously.
-    /// </summary>
-    [System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
-    [System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "UnusedMember.Global")]
-    [System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")]
-    public static class AsyncReceiveExtensions
-    {
-        static Task<bool> s_trueTask = Task.FromResult(true);
-        static Task<bool> s_falseTask = Task.FromResult(false);
-
-#region Receiving frames as a multipart message
-
-        /// <summary>
-        /// Receive a single frame from <paramref name="socket"/>, asynchronously.
-        /// </summary>
-        /// <param name="socket">The socket to receive from.</param>
-        /// <param name="expectedFrameCount">Specifies the initial capacity of the <see cref="List{T}"/> used
-        /// to buffer results. If the number of frames is known, set it here. If more frames arrive than expected,
-        /// an extra allocation will occur, but the result will still be correct.</param>
-        /// <param name="cancellationToken">The token used to propagate notification that this operation should be canceled.</param>
-        /// <returns>The content of the received message.</returns>
-        public static async Task<NetMQMessage> ReceiveMultipartMessageAsync(
-            this NetMQSocket socket, 
-            int expectedFrameCount = 4,
-            CancellationToken cancellationToken = default(CancellationToken))
-        {
-            var message = new NetMQMessage(expectedFrameCount);
-
-            while (true)
-            {
-                (byte[] bytes, bool more) = await socket.ReceiveFrameBytesAsync(cancellationToken);
-                message.Append(bytes);
-
-                if (!more)
-                {
-                    break;
-                }
-            }
-
-            return message;
-        }
-
-#endregion
-
-#region Receiving a frame as a byte array
-
-        /// <summary>
-        /// Receive a single frame from <paramref name="socket"/>, asynchronously.
-        /// </summary>
-        /// <param name="socket">The socket to receive from.</param>
-        /// <param name="cancellationToken">The token used to propagate notification that this operation should be canceled.</param>
-        /// <returns>The content of the received message frame and boolean indicate if another frame of the same message follows.</returns>
-        public static Task<(byte[], bool)> ReceiveFrameBytesAsync(
-            this NetMQSocket socket, 
-            CancellationToken cancellationToken = default(CancellationToken)
-        )
-        {
-            if (NetMQRuntime.Current == null)
-                throw new InvalidOperationException("NetMQRuntime must be created before calling async functions");
-
-            socket.AttachToRuntime();
-
-            var msg = new Msg();
-            msg.InitEmpty();
-
-            if (socket.TryReceive(ref msg, TimeSpan.Zero))
-            {
-                var data = msg.CloneData();
-                bool more = msg.HasMore;
-                msg.Close();
-
-                return Task.FromResult((data, more));
-            }
-
-            TaskCompletionSource<(byte[], bool)> source = new TaskCompletionSource<(byte[], bool)>();
-
-            CancellationTokenRegistration? registration = null;
-            if (cancellationToken.CanBeCanceled) 
-            {
-                registration = cancellationToken.Register(PropagateCancel);
-            }
-
-            void Listener(object sender, NetMQSocketEventArgs args)
-            {
-                if (socket.TryReceive(ref msg, TimeSpan.Zero))
-                {
-                    var data = msg.CloneData();
-                    bool more = msg.HasMore;
-                    msg.Close();
-
-                    socket.ReceiveReady -=  Listener;
-                    registration?.Dispose();
-                    source.TrySetResult((data, more));
-                }
-            }
-            
-            void PropagateCancel()
-            {
-                socket.ReceiveReady -= Listener;
-                registration?.Dispose();
-                source.TrySetCanceled();
-            }
-
-            socket.ReceiveReady += Listener;
-
-            return source.Task;
-        }
-
-#endregion
-
-#region Receiving a frame as a string
-
-        /// <summary>
-        /// Receive a single frame from <paramref name="socket"/>, asynchronously, and decode as a string using <see cref="SendReceiveConstants.DefaultEncoding"/>.
-        /// </summary>
-        /// <param name="socket">The socket to receive from.</param>
-        /// <param name="cancellationToken">The token used to propagate notification that this operation should be canceled.</param>
-        /// <returns>The content of the received message frame as a string and a boolean indicate if another frame of the same message follows.</returns>
-        public static Task<(string, bool)> ReceiveFrameStringAsync(
-            this NetMQSocket socket,
-            CancellationToken cancellationToken = default(CancellationToken)
-        )
-        {
-            return socket.ReceiveFrameStringAsync(SendReceiveConstants.DefaultEncoding, cancellationToken);
-        }
-
-
-        /// <summary>
-        /// Receive a single frame from <paramref name="socket"/>, asynchronously, and decode as a string using <paramref name="encoding"/>.
-        /// </summary>
-        /// <param name="socket">The socket to receive from.</param>
-        /// <param name="encoding">The encoding used to convert the frame's data to a string.</param>
-        /// <param name="cancellationToken">The token used to propagate notification that this operation should be canceled.</param>
-        /// <returns>The content of the received message frame as a string and boolean indicate if another frame of the same message follows..</returns>
-        public static Task<(string, bool)> ReceiveFrameStringAsync(
-            this NetMQSocket socket, 
-            Encoding encoding,
-            CancellationToken cancellationToken = default(CancellationToken))
-        {
-            if (NetMQRuntime.Current == null)
-                throw new InvalidOperationException("NetMQRuntime must be created before calling async functions");
-
-            socket.AttachToRuntime();
-
-            var msg = new Msg();
-            msg.InitEmpty();
-
-            if (socket.TryReceive(ref msg, TimeSpan.Zero))
-            {
-                var str = msg.Size > 0
-                    ? msg.GetString(encoding)
-                    : string.Empty;
-
-                msg.Close();
-                return Task.FromResult((str, msg.HasMore));
-            }
-
-            TaskCompletionSource<(string, bool)> source = new TaskCompletionSource<(string,bool)>();
-
-            CancellationTokenRegistration? registration = null;
-            if (cancellationToken.CanBeCanceled) 
-            {
-                registration = cancellationToken.Register(PropagateCancel);
-            }
-
-            void Listener(object sender, NetMQSocketEventArgs args)
-            {
-                if (socket.TryReceive(ref msg, TimeSpan.Zero))
-                {
-                    var str = msg.Size > 0
-                        ? msg.GetString(encoding)
-                        : string.Empty;
-                    bool more = msg.HasMore;
-                    msg.Close();
-
-                    socket.ReceiveReady -=  Listener;
-                    registration?.Dispose();
-                    source.TrySetResult((str, more));
-                }
-            }
-
-            void PropagateCancel()
-            {
-                socket.ReceiveReady -= Listener;
-                registration?.Dispose();
-                source.TrySetCanceled();
-            }
-
-            socket.ReceiveReady += Listener;
-
-            return source.Task;
-        }
-
-#endregion
-
-#region Skipping a message
-
-        /// <summary>
-        /// Receive a single frame from <paramref name="socket"/>, asynchronously, then ignore its content.
-        /// </summary>
-        /// <param name="socket">The socket to receive from.</param>
-        /// <param name="cancellationToken">The token used to propagate notification that this operation should be canceled.</param>
-        /// <returns>Boolean indicate if another frame of the same message follows</returns>
-        public static Task<bool> SkipFrameAsync(
-            this NetMQSocket socket, 
-            CancellationToken cancellationToken = default(CancellationToken)
-        )
-        {
-            if (NetMQRuntime.Current == null)
-                throw new InvalidOperationException("NetMQRuntime must be created before calling async functions");
-
-            socket.AttachToRuntime();
-
-            var msg = new Msg();
-            msg.InitEmpty();
-
-            if (socket.TryReceive(ref msg, TimeSpan.Zero))
-            {
-                bool more = msg.HasMore;
-                msg.Close();
-
-                return more ? s_trueTask : s_falseTask;
-            }
-
-            TaskCompletionSource<bool> source = new TaskCompletionSource<bool>();
-
-            CancellationTokenRegistration? registration = null;
-            if (cancellationToken.CanBeCanceled) 
-            {
-                registration = cancellationToken.Register(PropagateCancel);
-            }
-
-            void Listener(object sender, NetMQSocketEventArgs args)
-            {
-                if (socket.TryReceive(ref msg, TimeSpan.Zero))
-                {
-                    bool more = msg.HasMore;
-                    msg.Close();
-
-                    socket.ReceiveReady -=  Listener;
-                    registration?.Dispose();
-                    source.TrySetResult(more);
-                }
-            }
-
-            void PropagateCancel()
-            {
-                socket.ReceiveReady -= Listener;
-                registration?.Dispose();
-                source.TrySetCanceled();
-            }
-
-            socket.ReceiveReady += Listener;
-
-            return source.Task;
-        }
-
-
-#endregion
-
-#region Skipping all frames of a multipart message
-
-        /// <summary>
-        /// Receive all frames of the next message from <paramref name="socket"/>, asynchronously, then ignore their contents.
-        /// </summary>
-        /// <param name="socket">The socket to receive from.</param>
-        public static async Task SkipMultipartMessageAsync(this NetMQSocket socket)
-        {
-            while (true)
-            {
-                bool more = await socket.SkipFrameAsync();
-                if (!more)
-                    break;
-            }
-        }
-
-
-#endregion
-
-#region Receiving a routing key
-
-        /// <summary>
-        /// Receive a routing-key from <paramref name="socket"/>, blocking until one arrives.
-        /// </summary>
-        /// <param name="socket">The socket to receive from.</param>
-        /// <returns>The routing key and a boolean indicate if another frame of the same message follows.</returns>
-
-        public static async Task<(RoutingKey, bool)> ReceiveRoutingKeyAsync(this NetMQSocket socket)
-        {
-            var (bytes, more) = await socket.ReceiveFrameBytesAsync();
-
-            return (new RoutingKey(bytes), more);
-        }
-
-#endregion
-    }
-}
-
-#endif

+ 0 - 125
Communication/NetMQ/AtomicCounterPool.cs

@@ -1,125 +0,0 @@
-using NetMQ.Core.Utils;
-using System;
-using System.Threading;
-
-namespace NetMQ
-{
-    /// <summary>
-    /// The IBufferPool interface specifies two methods: Take, and Return.
-    /// These provide for taking atomic counters from a common pool, and returning them.
-    /// </summary>
-    public interface IAtomicCounterPool : IDisposable
-    {
-        /// <summary>
-        /// Take an AtomicCounter from the pool.
-        /// </summary>
-        /// <returns>an atomic counter</returns>
-        AtomicCounter Take();
-
-        /// <summary>
-        /// Return the given atomic counter to the common pool.
-        /// </summary>
-        /// <param name="counter">the atomic counter to return to the buffer-pool</param>
-        void Return(AtomicCounter counter);
-    }
-
-    /// <summary>
-    /// This simple implementation of <see cref="IAtomicCounterPool"/> does no pooling. Instead, it uses regular
-    /// .NET memory management to allocate a counter each time <see cref="Take"/> is called. Unused counters
-    /// passed to <see cref="Return"/> are simply left for the .NET garbage collector to deal with.
-    /// </summary>
-    public class GCAtomicCounterPool : IAtomicCounterPool
-    {
-        /// <summary>
-        /// Return a newly-allocated atomic counterfrom the pool.
-        /// </summary>
-        /// <returns>an atomic counter</returns>
-        public AtomicCounter Take()
-        {
-            return new AtomicCounter();
-        }
-
-        /// <summary>
-        /// The expectation of an actual pool is that this method returns the given counter to the manager pool.
-        /// This particular implementation does nothing.
-        /// </summary>
-        /// <param name="counter">a reference to the counter being returned</param>
-        public void Return(AtomicCounter counter)
-        { }
-
-        /// <summary>
-        /// The expectation of an actual pool is that the Dispose method will release the pools currently cached in this manager.
-        /// This particular implementation does nothing.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Release the counters currently cached in this manager (however in this case, this does nothing).
-        /// </summary>
-        /// <param name="disposing">true if managed resources are to be disposed</param>
-        protected virtual void Dispose(bool disposing)
-        {
-        }
-    }
-
-    /// <summary>
-    /// Contains a singleton instance of <see cref="IAtomicCounterPool"/> used for allocating atomic counters
-    /// for <see cref="Msg"/> instances with type <see cref="MsgType.Pool"/>.
-    /// </summary>
-    /// <remarks>
-    /// Sending and receiving messages with pooling mode, requires the use of atomic counters. 
-    /// You can use the AtomicCounterPool class to pool counters for reuse, reducing allocation, deallocation and garbage collection.
-    /// <para/>
-    /// The default implementation is <see cref="GCAtomicCounterPool"/>.
-    /// <list type="bullet">
-    /// <item>Call <see cref="SetGCCounterPool"/> to reinstate the default <see cref="GCBufferPool"/>.</item>
-    /// <item>Call <see cref="SetCustomCounterPool"/> to substitute a custom implementation for the allocation and
-    /// deallocation of atomic counters.</item>
-    /// </list>
-    /// </remarks>
-    public static class AtomicCounterPool
-    {
-        private static IAtomicCounterPool s_counterPool = new GCAtomicCounterPool();
-
-        /// <summary>
-        /// Set BufferPool to use the <see cref="GCBufferPool"/> (which it does by default).
-        /// </summary>
-        public static void SetGCCounterPool()
-        {
-            SetCustomCounterPool(new GCAtomicCounterPool());
-        }
-
-        /// <summary>
-        /// Set BufferPool to use the specified IAtomicCounterPool implementation to manage the pool.
-        /// </summary>
-        /// <param name="counterPool">the implementation of <see cref="IAtomicCounterPool"/> to use</param>
-        public static void SetCustomCounterPool(IAtomicCounterPool counterPool)
-        {
-            var prior = Interlocked.Exchange(ref s_counterPool, counterPool);
-
-            prior?.Dispose();
-        }
-
-        /// <summary>
-        /// Allocate an atomic counter from the current <see cref="IAtomicCounterPool"/>.
-        /// </summary>
-        /// <returns>an atomic counter</returns>
-        public static AtomicCounter Take()
-        {
-            return s_counterPool.Take();
-        }
-
-        /// <summary>
-        /// Returns <paramref name="counter"/> to the <see cref="IAtomicCounterPool"/>.
-        /// </summary>
-        /// <param name="counter">The atomic counter to be returned to the pool.</param>
-        public static void Return(AtomicCounter counter)
-        {
-            s_counterPool.Return(counter);
-        }
-    }
-}

+ 0 - 207
Communication/NetMQ/BufferPool.cs

@@ -1,207 +0,0 @@
-using System;
-using System.ServiceModel.Channels;
-using System.Threading;
-
-namespace NetMQ
-{    
-    /// <summary>
-    /// The IBufferPool interface specifies two methods: Take, and Return.
-    /// These provide for taking byte-array data from a common pool, and returning it.
-    /// </summary>
-    public interface IBufferPool : IDisposable
-    {
-        /// <summary>
-        /// Take byte-array storage from the buffer-pool.
-        /// </summary>
-        /// <param name="size">the number of bytes to take</param>
-        /// <returns>a byte-array that comes from the buffer-pool</returns>
-        byte[] Take(int size);
-
-        /// <summary>
-        /// Return the given byte-array buffer to the common buffer-pool.
-        /// </summary>
-        /// <param name="buffer">the byte-array to return to the buffer-pool</param>
-        void Return(byte[] buffer);
-    }
-
-    /// <summary>
-    /// This implementation of <see cref="IBufferPool"/> uses WCF's <see cref="BufferManager"/>
-    /// class to manage a pool of buffers.
-    /// </summary>
-    public class BufferManagerBufferPool : IBufferPool
-    {
-        private readonly BufferManager m_bufferManager;
-
-        /// <summary>
-        /// Create a new BufferManagerBufferPool with the specified maximum buffer pool size
-        /// and a maximum size for each individual buffer in the pool.
-        /// </summary>
-        /// <param name="maxBufferPoolSize">the maximum size to allow for the buffer pool</param>
-        /// <param name="maxBufferSize">the maximum size to allow for each individual buffer in the pool</param>
-        /// <exception cref="InsufficientMemoryException">There was insufficient memory to create the requested buffer pool.</exception>
-        /// <exception cref="ArgumentOutOfRangeException">Either maxBufferPoolSize or maxBufferSize was less than zero.</exception>
-        public BufferManagerBufferPool(long maxBufferPoolSize, int maxBufferSize)
-        {
-            m_bufferManager = BufferManager.CreateBufferManager(maxBufferPoolSize, maxBufferSize);
-        }
-
-        /// <summary>
-        /// Return a byte-array buffer of at least the specified size from the pool.
-        /// </summary>
-        /// <param name="size">the size in bytes of the requested buffer</param>
-        /// <returns>a byte-array that is the requested size</returns>
-        /// <exception cref="ArgumentOutOfRangeException">size cannot be less than zero</exception>
-        public byte[] Take(int size)
-        {
-            return m_bufferManager.TakeBuffer(size);
-        }
-
-        /// <summary>
-        /// Return the given buffer to this manager pool.
-        /// </summary>
-        /// <param name="buffer">a reference to the buffer being returned</param>
-        /// <exception cref="ArgumentException">the Length of buffer does not match the pool's buffer length property</exception>
-        /// <exception cref="ArgumentNullException">the buffer reference cannot be null</exception>
-        public void Return(byte[] buffer)
-        {
-            m_bufferManager.ReturnBuffer(buffer);
-        }
-
-        /// <summary>
-        /// Release the buffers currently cached in this manager.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Release the buffers currently cached in this manager.
-        /// </summary>
-        /// <param name="disposing">true if managed resources are to be disposed</param>
-        protected virtual void Dispose(bool disposing)
-        {
-            if (!disposing)
-                return;
-
-            m_bufferManager.Clear();
-        }
-    }
-
-    /// <summary>
-    /// This simple implementation of <see cref="IBufferPool"/> does no buffer pooling. Instead, it uses regular
-    /// .NET memory management to allocate a buffer each time <see cref="Take"/> is called. Unused buffers
-    /// passed to <see cref="Return"/> are simply left for the .NET garbage collector to deal with.
-    /// </summary>
-    public class GCBufferPool : IBufferPool
-    {
-        /// <summary>
-        /// Return a newly-allocated byte-array buffer of at least the specified size from the pool.
-        /// </summary>
-        /// <param name="size">the size in bytes of the requested buffer</param>
-        /// <returns>a byte-array that is the requested size</returns>
-        /// <exception cref="OutOfMemoryException">there is not sufficient memory to allocate the requested memory</exception>
-        public byte[] Take(int size)
-        {
-            return new byte[size];
-        }
-
-        /// <summary>
-        /// The expectation of an actual buffer-manager is that this method returns the given buffer to the manager pool.
-        /// This particular implementation does nothing.
-        /// </summary>
-        /// <param name="buffer">a reference to the buffer being returned</param>
-        public void Return(byte[] buffer)
-        { }
-
-        /// <summary>
-        /// The expectation of an actual buffer-manager is that the Dispose method will release the buffers currently cached in this manager.
-        /// This particular implementation does nothing.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Release the buffers currently cached in this manager (however in this case, this does nothing).
-        /// </summary>
-        /// <param name="disposing">true if managed resources are to be disposed</param>
-        protected virtual void Dispose(bool disposing)
-        {
-        }
-    }
-
-    /// <summary>
-    /// Contains a singleton instance of <see cref="IBufferPool"/> used for allocating byte arrays
-    /// for <see cref="Msg"/> instances with type <see cref="MsgType.Pool"/>.
-    /// </summary>
-    /// <remarks>
-    /// Sending and receiving message frames requires the use of buffers (byte arrays), which are expensive to create and destroy.
-    /// You can use the BufferPool class to pool buffers for reuse, reducing allocation, deallocation and garbage collection.
-    /// <para/>
-    /// The default implementation is <see cref="GCBufferPool"/>.
-    /// <list type="bullet">
-    /// <item>Call <see cref="SetBufferManagerBufferPool"/> to replace it with a <see cref="BufferManagerBufferPool"/>.</item>
-    /// <item>Call <see cref="SetGCBufferPool"/> to reinstate the default <see cref="GCBufferPool"/>.</item>
-    /// <item>Call <see cref="SetCustomBufferPool"/> to substitute a custom implementation for the allocation and
-    /// deallocation of message buffers.</item>
-    /// </list>
-    /// </remarks>
-    public static class BufferPool
-    {
-        private static IBufferPool s_bufferPool = new GCBufferPool();
-
-        /// <summary>
-        /// Set BufferPool to use the <see cref="GCBufferPool"/> (which it does by default).
-        /// </summary>
-        public static void SetGCBufferPool()
-        {
-            SetCustomBufferPool(new GCBufferPool());
-        }
-
-        /// <summary>
-        /// Set BufferPool to use the <see cref="BufferManagerBufferPool"/> to manage the buffer-pool.
-        /// </summary>
-        /// <param name="maxBufferPoolSize">the maximum size to allow for the buffer pool</param>
-        /// <param name="maxBufferSize">the maximum size to allow for each individual buffer in the pool</param>
-        /// <exception cref="InsufficientMemoryException">There was insufficient memory to create the requested buffer pool.</exception>
-        /// <exception cref="ArgumentOutOfRangeException">Either maxBufferPoolSize or maxBufferSize was less than zero.</exception>
-        public static void SetBufferManagerBufferPool(long maxBufferPoolSize, int maxBufferSize)
-        {
-            SetCustomBufferPool(new BufferManagerBufferPool(maxBufferPoolSize, maxBufferSize));
-        }
-
-        /// <summary>
-        /// Set BufferPool to use the specified IBufferPool implementation to manage the buffer-pool.
-        /// </summary>
-        /// <param name="bufferPool">the implementation of <see cref="IBufferPool"/> to use</param>
-        public static void SetCustomBufferPool(IBufferPool bufferPool)
-        {
-            var prior = Interlocked.Exchange(ref s_bufferPool, bufferPool);
-
-            prior?.Dispose();
-        }
-
-        /// <summary>
-        /// Allocate a buffer of at least <paramref name="size"/> bytes from the current <see cref="IBufferPool"/>.
-        /// </summary>
-        /// <param name="size">The minimum size required, in bytes.</param>
-        /// <returns>A byte array having at least <paramref name="size"/> bytes.</returns>
-        public static byte[] Take(int size)
-        {
-            return s_bufferPool.Take(size);
-        }
-
-        /// <summary>
-        /// Returns <paramref name="buffer"/> to the <see cref="IBufferPool"/>.
-        /// </summary>
-        /// <param name="buffer">The byte array to be returned to the pool.</param>
-        public static void Return(byte[] buffer)
-        {
-            s_bufferPool.Return(buffer);
-        }
-    }
-}

+ 0 - 135
Communication/NetMQ/Core/Address.cs

@@ -1,135 +0,0 @@
-/*
-    Copyright (c) 2012 Spotify AB
-    Copyright (c) 2012-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using System.Net;
-
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Class Address contains a specification of a protocol and an MqEndPoint.
-    /// </summary>
-    internal sealed class Address
-    {
-        /// <summary>
-        /// The string-literal "inproc"
-        /// - this denotes in-process, or inter-thread, communication.
-        /// </summary>
-        public const string InProcProtocol = "inproc";
-
-        /// <summary>
-        /// The string-literal "tcp"
-        /// - this denotes TCP communication over the network.
-        /// </summary>
-        public const string TcpProtocol = "tcp";
-
-        /// <summary>
-        /// The string-literal "ipc"
-        /// - this denotes inter-process communication, which on NetMQ is exactly the same as TCP.
-        /// </summary>
-        public const string IpcProtocol = "ipc";
-
-        /// <summary>
-        /// The string-literal "pgm"
-        /// - this denotes the Pragmatic General Multicast (PGM) reliable multicast protocol.
-        /// </summary>
-        public const string PgmProtocol = "pgm";
-
-        /// <summary>
-        /// The string-literal "epgm"
-        /// - this denotes the Encapsulated PGM protocol.
-        /// </summary>
-        public const string EpgmProtocol = "epgm";
-
-        /// <summary>
-        /// Interface IZAddress specifies that Resolve and property Address must be implemented.
-        /// </summary>
-        public interface IZAddress
-        {
-            void Resolve(string name, bool ip4Only);
-
-            IPEndPoint? Address { get; }
-            string Protocol { get; }
-        }
-
-        /// <summary>
-        /// Create a new Address instance with the given protocol and text expression of an address.
-        /// </summary>
-        /// <param name="protocol">the protocol of this Address - as in tcp, ipc, pgm</param>
-        /// <param name="address">a text representation of the address</param>
-        public Address(string protocol, string address)
-        {
-            Protocol = protocol;
-            AddressString = address;
-            Resolved = null;
-        }
-
-        /// <summary>
-        /// Create a new Address instance based upon the given endpoint, assuming a protocol of tcp.
-        /// </summary>
-        /// <param name="endpoint">the subclass of EndPoint to base this Address upon</param>
-        public Address(EndPoint endpoint)
-        {
-            Protocol = TcpProtocol;
-
-            var dnsEndPoint = endpoint as DnsEndPoint;
-            if (dnsEndPoint != null)
-            {
-                AddressString = dnsEndPoint.Host + ":" + dnsEndPoint.Port;
-                return;
-            }
-
-            var ipEndPoint = endpoint as IPEndPoint;
-            if (ipEndPoint != null)
-            {
-                AddressString = ipEndPoint.Address + ":" + ipEndPoint.Port;
-                return;
-            }
-
-            AddressString = endpoint.ToString();
-        }
-
-
-        public override string ToString()
-        {
-            if (Resolved != null)
-            {
-                switch (Protocol)
-                {
-                    case TcpProtocol: return Resolved.ToString();
-                    case IpcProtocol: return Resolved.ToString();
-                    case PgmProtocol: return Resolved.ToString();
-                }
-            }
-
-            if (!string.IsNullOrEmpty(Protocol) && !string.IsNullOrEmpty(AddressString))
-            {
-                return Protocol + "://" + AddressString;
-            }
-
-            return base.ToString();
-        }
-
-        public string Protocol { get; }
-
-        public string AddressString { get; }
-
-        public IZAddress? Resolved { get; set; }
-    }
-}

+ 0 - 62
Communication/NetMQ/Core/Command.cs

@@ -1,62 +0,0 @@
-/*
-    Copyright (c) 2009-2011 250bpm s.r.o.
-    Copyright (c) 2007-2009 iMatix Corporation
-    Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Defines a command sent between threads.
-    /// </summary>
-    internal struct Command
-    {
-        /// <summary>
-        /// Create a new Command object for the given destination, type, and optional argument.
-        /// </summary>
-        /// <param name="destination">a ZObject that denotes the destination for this command</param>
-        /// <param name="type">the CommandType of the new command</param>
-        /// <param name="arg">an Object to comprise the argument for the command (optional)</param>
-        public Command(ZObject? destination, CommandType type, object? arg = null) : this()
-        {
-            Destination = destination;
-            CommandType = type;
-            Arg = arg;
-        }
-
-        /// <summary>The destination to which the command should be applied.</summary>
-        public ZObject? Destination { get; }
-
-        /// <summary>The type of this command.</summary>
-        public CommandType CommandType { get; }
-
-        /// <summary>
-        /// Get the argument to this command.
-        /// </summary>
-        public object? Arg { get; }
-
-        /// <summary>
-        /// Override of ToString, which returns a string in the form [ command-type, destination ].
-        /// </summary>
-        /// <returns>a string that denotes the command-type and destination</returns>
-        public override string ToString()
-        {
-            return base.ToString() + "[" + CommandType + ", " + Destination + "]";
-        }
-    }
-}

+ 0 - 116
Communication/NetMQ/Core/CommandType.cs

@@ -1,116 +0,0 @@
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Enumeration of possible <see cref="Command"/> types.
-    /// </summary>
-    /// <remarks>
-    /// The value of <see cref="Command.CommandType"/> denotes what action
-    /// the command will perform.
-    /// </remarks>
-    internal enum CommandType
-    {
-        None = 0,
-
-        /// <summary>
-        /// Sent to I/O thread to let it know that it should
-        /// terminate itself.
-        /// </summary>
-        Stop,
-
-        /// <summary>
-        /// Sent to I/O object to make it register with its I/O thread
-        /// </summary>
-        Plug,
-
-        /// <summary>
-        /// Sent to socket to let it know about the newly created object.
-        /// </summary>
-        Own,
-
-        /// <summary>
-        /// Attach the engine to the session. If engine is NULL, it informs
-        /// session that the connection has failed.
-        /// </summary>
-        Attach,
-
-        /// <summary>
-        /// Sent from session to socket to establish pipe(s) between them.
-        /// Caller must have used inc_seqnum before sending the command.
-        /// </summary>
-        Bind,
-
-        /// <summary>
-        /// Sent by pipe writer to inform dormant pipe reader that there
-        /// are messages in the pipe.
-        /// </summary>
-        ActivateRead,
-
-        /// <summary>
-        /// Sent by pipe reader to inform pipe writer how many
-        /// messages it has read so far.
-        /// </summary>
-        ActivateWrite,
-
-        /// <summary>
-        /// Sent by pipe reader to writer after creating a new inpipe.
-        /// The parameter is actually of type pipe_t::upipe_t, however,
-        /// its definition is private so we'll have to do with void*.
-        /// </summary>
-        Hiccup,
-
-        /// <summary>
-        /// Sent by pipe reader to pipe writer to ask it to terminate
-        /// its end of the pipe.
-        /// </summary>
-        PipeTerm,
-
-        /// <summary>
-        /// Pipe writer acknowledges pipe_term command.
-        /// </summary>
-        PipeTermAck,
-
-        /// <summary>
-        /// Sent by I/O object to the socket to request the shutdown of
-        /// the I/O object.
-        /// </summary>
-        TermReq,
-
-        /// <summary>
-        /// Sent by socket to I/O object to start its shutdown.
-        /// </summary>
-        Term,
-
-        /// <summary>
-        /// Sent by I/O object to the socket to acknowledge it has
-        /// shut down.
-        /// </summary>
-        TermAck,
-
-        /// <summary>
-        /// Transfers the ownership of the closed socket
-        /// to the reaper thread.
-        /// </summary>
-        Reap,
-
-        /// <summary>
-        /// Closed socket notifies the reaper that it's already deallocated.
-        /// </summary>
-        Reaped,
-
-        /// <summary>
-        /// Sent by reaper thread to the term thread when all the sockets
-        /// have successfully been deallocated.
-        /// </summary>
-        Done,
-
-        /// <summary>
-        /// Send to reaper to stop the reaper immediatly
-        /// </summary>
-        ForceStop,
-        
-        /// <summary>
-        /// Send a cancellation request to the socket from a cancellation token
-        /// </summary>
-        CancellationRequested
-    }
-}

+ 0 - 106
Communication/NetMQ/Core/Config.cs

@@ -1,106 +0,0 @@
-/*
-    Copyright (c) 2009-2011 250bpm s.r.o.
-    Copyright (c) 2007-2009 iMatix Corporation
-    Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// This class exists to hold constant values that comprise the internal configuration of the messaging system.
-    /// </summary>
-    internal static class Config
-    {
-        /// <summary>
-        /// Number of new messages in message pipe needed to trigger new memory
-        /// allocation. Setting this parameter to 256 decreases the impact of
-        /// memory allocation by approximately 99.6%
-        /// </summary>
-        public const int MessagePipeGranularity = 256;
-
-        /// <summary>
-        /// Commands in pipe per allocation event.
-        /// </summary>
-        public const int CommandPipeGranularity = 16;
-
-        /// <summary>
-        /// Determines how often does socket poll for new commands when it
-        /// still has unprocessed messages to handle. Thus, if it is set to 100,
-        /// socket will process 100 inbound messages before doing the poll.
-        /// If there are no unprocessed messages available, poll is done
-        /// immediately. Decreasing the value trades overall latency for more
-        /// real-time behaviour (less latency peaks).
-        /// </summary>
-        public const int InboundPollRate = 100;
-
-        /// <summary>
-        /// Maximal batching size for engines with receiving functionality.
-        /// So, if there are 10 messages that fit into the batch size, all of
-        /// them may be read by a single 'recv' system call, thus avoiding
-        /// unnecessary network stack traversals.
-        /// </summary>
-        public const int InBatchSize = 8192;
-
-        /// <summary>
-        /// Maximal batching size for engines with sending functionality.
-        /// So, if there are 10 messages that fit into the batch size, all of
-        /// them may be written by a single 'send' system call, thus avoiding
-        /// unnecessary network stack traversals.
-        /// </summary>
-        public const int OutBatchSize = 8192;
-
-        /// <summary>
-        /// Maximal delta between high and low watermark.
-        /// </summary>
-        public const int MaxWatermarkDelta = 1024;
-
-        /// <summary>
-        /// Maximum number of events the I/O thread can process in one go.
-        /// </summary>
-        public const int MaxIOEvents = 256;
-
-        /// <summary>
-        /// Maximal delay to process command in API thread (in CPU ticks).
-        /// 3,000,000 ticks equals to 1 - 2 milliseconds on current CPUs.
-        /// Note that delay is only applied when there is continuous stream of
-        /// messages to process. If not so, commands are processed immediately.
-        /// </summary>
-        public const int MaxCommandDelay = 3000000;
-
-        /// <summary>
-        /// Low-precision clock precision in CPU ticks. 1ms. Value of 1000000
-        /// should be OK for CPU frequencies above 1GHz. If should work
-        /// reasonably well for CPU frequencies above 500MHz. For lower CPU
-        /// frequencies you may consider lowering this value to get best
-        /// possible latencies.
-        /// </summary>
-        public const int ClockPrecision = 1000000;
-
-        /// <summary>
-        /// Maximum transport data unit size for PGM (TPDU).
-        /// </summary>
-        public const int PgmMaxTPDU = 1500;
-
-        /// <summary>
-        /// On some OSes the signaler has to be emulated using a TCP
-        /// connection. In such cases following port is used.
-        /// </summary>
-        public const int SignalerPort = 5906;
-    }
-}
-

+ 0 - 520
Communication/NetMQ/Core/Ctx.cs

@@ -1,520 +0,0 @@
-/*
-    Copyright (c) 2007-2012 iMatix Corporation
-    Copyright (c) 2009-2011 250bpm s.r.o.
-    Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#nullable disable
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Threading;
-
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Objects of class Ctx are intended to encapsulate all of the global state
-    /// associated with the NetMQ library. This contains the sockets, and manages interaction
-    /// between them.
-    /// </summary>
-    internal sealed class Ctx
-    {
-        internal const int DefaultIOThreads = 1;
-        internal const int DefaultMaxSockets = 1024;
-
-        #region Nested class: Endpoint
-
-        /// <summary>
-        /// Information associated with inproc endpoint. Note that endpoint options
-        /// are registered as well so that the peer can access them without a need
-        /// for synchronisation, handshaking or similar.
-        /// </summary>
-        public class Endpoint
-        {
-            /// <summary>
-            /// Create a new Endpoint with the given socket.
-            /// </summary>
-            /// <param name="socket">the socket for this new Endpoint</param>
-            /// <param name="options">the Options to assign to this new Endpoint</param>
-            public Endpoint([NotNull] SocketBase socket, [NotNull] Options options)
-            {
-                Socket = socket;
-                Options = options;
-            }
-
-            /// <summary>
-            /// Get the socket associated with this Endpoint.
-            /// </summary>
-            [NotNull]
-            public SocketBase Socket { get; }
-
-            /// <summary>
-            /// Get the Options of this Endpoint.
-            /// </summary>
-            [NotNull]
-            public Options Options { get; }
-        }
-
-        #endregion
-
-        /// <summary>
-        /// Sockets belonging to this context. We need the list so that
-        /// we can notify the sockets when zmq_term() is called. The sockets
-        /// will return ETERM then.
-        /// </summary>
-        private readonly List<SocketBase> m_sockets = new List<SocketBase>();
-
-        /// <summary>
-        /// List of unused thread slots.
-        /// </summary>
-        private readonly Stack<int> m_emptySlots = new Stack<int>();
-
-        /// <summary>
-        /// If true, zmq_init has been called but no socket has been created
-        /// yet. Launching of I/O threads is delayed.
-        /// </summary>
-        private volatile bool m_starting = true;
-
-        /// <summary>
-        /// If true, zmq_term was already called.
-        /// </summary>
-        private bool m_terminating;
-
-        /// <summary>
-        /// This object is for synchronisation of accesses to global slot-related data:
-        /// sockets, empty_slots, terminating. It also synchronises
-        /// access to zombie sockets as such (as opposed to slots) and provides
-        /// a memory barrier to ensure that all CPU cores see the same data.
-        /// </summary>
-        private readonly object m_slotSync = new object();
-
-        /// <summary>
-        /// The reaper thread.
-        /// </summary>
-         private Reaper m_reaper;
-
-        /// <summary>
-        /// List of I/O threads.
-        /// </summary>
-        private readonly List<IOThread> m_ioThreads = new List<IOThread>();
-
-        /// <summary>
-        /// Length of the mailbox-array.
-        /// </summary>
-        private int m_slotCount;
-
-        /// <summary>
-        /// Array of pointers to mailboxes for both application and I/O threads.
-        /// </summary>
-        private IMailbox[] m_slots;
-
-        /// <summary>
-        /// Mailbox for zmq_term thread.
-        /// </summary>
-        private readonly Mailbox m_termMailbox = new Mailbox("terminator");
-
-        /// <summary>
-        /// Dictionary containing the inproc endpoints within this context.
-        /// </summary>
-        private readonly Dictionary<string, Endpoint> m_endpoints = new Dictionary<string, Endpoint>();
-
-        /// <summary>
-        /// This object provides synchronisation of access to the list of inproc endpoints.
-        /// </summary>
-        private readonly object m_endpointsSync = new object();
-
-        /// <summary>
-        /// The highest socket-id that has been assigned thus far.
-        /// </summary>
-        private static int s_maxSocketId;
-
-        /// <summary>
-        /// The maximum number of sockets that can be opened at the same time.
-        /// </summary>
-        private int m_maxSockets = DefaultMaxSockets;
-
-        /// <summary>
-        /// The number of I/O threads to launch.
-        /// </summary>
-        private int m_ioThreadCount = DefaultIOThreads;
-
-        /// <summary>
-        /// This object is used to synchronize access to context options.
-        /// </summary>
-        private readonly object m_optSync = new object();
-
-        /// <summary>
-        /// The thread-id for the termination (the equivalent of the zmq_term) thread.
-        /// </summary>
-        public const int TermTid = 0;
-
-        /// <summary>
-        /// This is the thread-id to assign to the Reaper (value is 1).
-        /// </summary>
-        public const int ReaperTid = 1;
-
-        /// <summary>
-        /// This function is called when user invokes zmq_term. If there are
-        /// no more sockets open it'll cause all the infrastructure to be shut
-        /// down. If there are open sockets still, the deallocation happens
-        /// after the last one is closed.
-        /// </summary>
-        public void Terminate(bool block)
-        {
-            Monitor.Enter(m_slotSync);
-
-            if (!m_starting)
-            {
-                // Check whether termination was already underway, but interrupted and now
-                // restarted.
-                bool restarted = m_terminating;
-                m_terminating = true;
-                Monitor.Exit(m_slotSync);
-
-                // First attempt to terminate the context.
-                if (!restarted)
-                {
-                    // First send stop command to sockets so that any blocking calls
-                    // can be interrupted. If there are no sockets we can ask reaper
-                    // thread to stop.
-                    Monitor.Enter(m_slotSync);
-                    try
-                    {
-                        foreach (var socket in m_sockets)
-                            socket.Stop();
-
-                        if (!block)
-                            m_reaper.ForceStop();
-                        else if (m_sockets.Count == 0)
-                            m_reaper.Stop();
-                    }
-                    finally
-                    {
-                        Monitor.Exit(m_slotSync);
-                    }
-                }
-
-                // Wait till reaper thread closes all the sockets.
-                var found = m_termMailbox.TryRecv(-1, out Command command);
-
-                Debug.Assert(found);
-                Debug.Assert(command.CommandType == CommandType.Done);
-                Monitor.Enter(m_slotSync);
-            }
-            Monitor.Exit(m_slotSync);
-
-            // Deallocate the resources.
-            foreach (IOThread it in m_ioThreads)
-                it.Stop();
-
-            foreach (IOThread it in m_ioThreads)
-                it.Destroy();
-
-            m_reaper?.Destroy();
-
-            m_termMailbox.Close();
-        }
-
-        public int IOThreadCount
-        {
-            get => m_ioThreadCount;
-            set
-            {
-                if (value < 0)
-                    throw new ArgumentOutOfRangeException(nameof(value), value, "Must be zero or greater");
-                lock (m_optSync)
-                    m_ioThreadCount = value;
-            }
-        }
-
-        public int MaxSockets
-        {
-            get => m_maxSockets;
-            set
-            {
-                if (value <= 0)
-                    throw new ArgumentOutOfRangeException(nameof(value), value, "Must be greater than zero");
-                lock (m_optSync)
-                    m_maxSockets = value;
-            }
-        }
-
-        /// <summary>
-        /// Create and return a new socket of the given type, and initialize this Ctx if this is the first one.
-        /// </summary>
-        /// <param name="type">the type of socket to create</param>
-        /// <returns>the newly-created socket</returns>
-        /// <exception cref="TerminatingException">Cannot create new socket while terminating.</exception>
-        /// <exception cref="NetMQException">Maximum number of sockets reached.</exception>
-        /// <exception cref="TerminatingException">The context (Ctx) must not be already terminating.</exception>
-        public SocketBase CreateSocket(ZmqSocketType type)
-        {
-            lock (m_slotSync)
-            {
-                if (m_starting)
-                {
-                    m_starting = false;
-                    // Initialise the array of mailboxes. Additional three slots are for
-                    // zmq_term thread and reaper thread.
-
-                    int ios;
-                    int mazmq;
-
-                    lock (m_optSync)
-                    {
-                        mazmq = m_maxSockets;
-                        ios = m_ioThreadCount;
-                    }
-                    m_slotCount = mazmq + ios + 2;
-                    m_slots = new IMailbox[m_slotCount];
-                    //alloc_Debug.Assert(slots);
-
-                    // Initialise the infrastructure for zmq_term thread.
-                    m_slots[TermTid] = m_termMailbox;
-
-                    // Create the reaper thread.
-                    m_reaper = new Reaper(this, ReaperTid);
-                    //alloc_Debug.Assert(reaper);
-                    m_slots[ReaperTid] = m_reaper.Mailbox;
-                    m_reaper.Start();
-
-                    // Create I/O thread objects and launch them.
-                    for (int i = 2; i != ios + 2; i++)
-                    {
-                        var ioThread = new IOThread(this, i);
-                        //alloc_Debug.Assert(io_thread);
-                        m_ioThreads.Add(ioThread);
-                        m_slots[i] = ioThread.Mailbox;
-                        ioThread.Start();
-                    }
-
-                    // In the unused part of the slot array, create a list of empty slots.
-                    for (int i = m_slotCount - 1; i >= ios + 2; i--)
-                    {
-                        m_emptySlots.Push(i);
-                        m_slots[i] = null;
-                    }
-                }
-
-                // Once zmq_term() was called, we can't create new sockets.
-                if (m_terminating)
-                {
-                    string xMsg = $"Ctx.CreateSocket({type}), cannot create new socket while terminating.";
-                    throw new TerminatingException(innerException: null, message: xMsg);
-                }
-
-                // If max_sockets limit was reached, return error.
-                if (m_emptySlots.Count == 0)
-                {
-#if DEBUG
-                    string xMsg = $"Ctx.CreateSocket({type}), max number of sockets {m_maxSockets} reached.";
-                    throw NetMQException.Create(xMsg, ErrorCode.TooManyOpenSockets);
-#else
-                    throw NetMQException.Create(ErrorCode.TooManyOpenSockets);
-#endif
-                }
-
-                // Choose a slot for the socket.
-                int slot = m_emptySlots.Pop();
-
-                // Generate new unique socket ID.
-                int socketId = Interlocked.Increment(ref s_maxSocketId);
-
-                // Create the socket and register its mailbox.
-                SocketBase s = SocketBase.Create(type, this, slot, socketId);
-
-                m_sockets.Add(s);
-                m_slots[slot] = s.Mailbox;
-
-                //LOG.debug("NEW Slot [" + slot + "] " + s);
-
-                return s;
-            }
-        }
-
-        /// <summary>
-        /// Destroy the given socket - which means to remove it from the list of active sockets,
-        /// and add it to the list of unused sockets to be terminated.
-        /// </summary>
-        /// <param name="socket">the socket to destroy</param>
-        /// <remarks>
-        /// If this was the last socket, then stop the reaper.
-        /// </remarks>
-        public void DestroySocket([NotNull] SocketBase socket)
-        {
-            // Free the associated thread slot.
-            lock (m_slotSync)
-            {
-                int threadId = socket.ThreadId;
-                m_emptySlots.Push(threadId);
-                m_slots[threadId].Close();
-                m_slots[threadId] = null;
-
-                // Remove the socket from the list of sockets.
-                m_sockets.Remove(socket);
-
-                // If zmq_term() was already called and there are no more socket
-                // we can ask reaper thread to terminate.
-                if (m_terminating && m_sockets.Count == 0)
-                    m_reaper.Stop();
-            }
-
-            //LOG.debug("Released Slot [" + socket_ + "] ");
-        }
-
-        /// <summary>
-        /// Returns reaper thread object.
-        /// </summary>
-        public ZObject GetReaper()
-        {
-            return m_reaper;
-        }
-
-        /// <summary>
-        /// Send a command to the given destination thread.
-        /// </summary>
-        public void SendCommand(int threadId, [NotNull] Command command)
-        {
-            m_slots[threadId].Send(command);
-        }
-
-        /// <summary>
-        /// Returns the <see cref="IOThread"/> that is the least busy at the moment.
-        /// </summary>
-        /// <paramref name="affinity">Which threads are eligible (0 = all).</paramref>
-        /// <returns>The least busy thread, or <c>null</c> if none is available.</returns>
-        
-        public IOThread ChooseIOThread(long affinity)
-        {
-            if (m_ioThreads.Count == 0)
-                return null;
-
-            // Find the I/O thread with minimum load.
-            int minLoad = -1;
-            IOThread selectedIOThread = null;
-
-            for (int i = 0; i != m_ioThreads.Count; i++)
-            {
-                var ioThread = m_ioThreads[i];
-
-                if (affinity == 0 || (affinity & (1L << i)) > 0)
-                {
-                    if (selectedIOThread == null || ioThread.Load < minLoad)
-                    {
-                        minLoad = ioThread.Load;
-                        selectedIOThread = ioThread;
-                    }
-                }
-            }
-            return selectedIOThread;
-        }
-
-        /// <summary>
-        /// Save the given address and Endpoint within our internal list.
-        /// This is used for management of inproc endpoints.
-        /// </summary>
-        /// <param name="address">the textual name to give this endpoint</param>
-        /// <param name="endpoint">the Endpoint to remember</param>
-        /// <returns>true if the given address was NOT already registered</returns>
-        public bool RegisterEndpoint([NotNull] string address, [NotNull] Endpoint endpoint)
-        {
-            lock (m_endpointsSync)
-            {
-                if (m_endpoints.ContainsKey(address))
-                    return false;
-
-                m_endpoints[address] = endpoint;
-                return true;
-            }
-        }
-
-        /// <summary>
-        /// Un-register the given address/socket, by removing it from the contained list of endpoints.
-        /// </summary>
-        /// <param name="address">the (string) address denoting the endpoint to unregister</param>
-        /// <param name="socket">the socket associated with that endpoint</param>
-        /// <returns>true if the endpoint having this address and socket is found, false otherwise</returns>
-        public bool UnregisterEndpoint([NotNull] string address, [NotNull] SocketBase socket)
-        {
-            lock (m_endpointsSync)
-            {
-
-                if (!m_endpoints.TryGetValue(address, out Endpoint endpoint))
-                    return false;
-
-                if (socket != endpoint.Socket)
-                    return false;
-
-                m_endpoints.Remove(address);
-                return true;
-            }
-        }
-
-        /// <summary>
-        /// Remove from the list of endpoints, all endpoints that reference the given socket.
-        /// </summary>
-        /// <param name="socket">the socket to remove all references to</param>
-        public void UnregisterEndpoints([NotNull] SocketBase socket)
-        {
-            lock (m_endpointsSync)
-            {
-                IList<string> removeList = m_endpoints.Where(e => e.Value.Socket == socket).Select(e => e.Key).ToList();
-
-                foreach (var item in removeList)
-                    m_endpoints.Remove(item);
-            }
-        }
-
-        /// <summary>
-        /// Return the EndPoint that has the given address, and increments the seqnum of the associated socket.
-        /// </summary>
-        /// <param name="addr">the (string) address to match against the endpoints</param>
-        /// <returns>the Endpoint that was found</returns>
-        /// <exception cref="EndpointNotFoundException">The given address was not found in the list of endpoints.</exception>
-        /// <remarks>
-        /// By calling this method, the socket associated with that returned EndPoint has it's Seqnum incremented,
-        /// in order to prevent it from being de-allocated before a command can be sent to it.
-        /// </remarks>
-        public Endpoint FindEndpoint( string addr)
-        {
-            Debug.Assert(addr != null);
-
-            lock (m_endpointsSync)
-            {
-                if (!m_endpoints.ContainsKey(addr))
-                    throw new EndpointNotFoundException();
-
-                var endpoint = m_endpoints[addr];
-
-                if (endpoint == null)
-                    throw new EndpointNotFoundException();
-
-                // Increment the command sequence number of the peer so that it won't
-                // get deallocated until "bind" command is issued by the caller.
-                // The subsequent 'bind' has to be called with inc_seqnum parameter
-                // set to false, so that the seqnum isn't incremented twice.
-                endpoint.Socket.IncSeqnum();
-
-                return endpoint;
-            }
-        }
-    }
-}

+ 0 - 66
Communication/NetMQ/Core/ErrorHelper.cs

@@ -1,66 +0,0 @@
-using System.Diagnostics;
-using System.Net.Sockets;
-
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Class ErrorHelper provides one static method - ToErrorCode, for converting a SocketError to the equivalent ErrorCode.
-    /// </summary>
-    internal static class ErrorHelper
-    {
-        /// <summary>
-        /// Return the ErrorCode that is the closest equivalent to the given SocketError.
-        /// </summary>
-        /// <param name="error">the SocketError to convert from</param>
-        /// <returns>an ErrorCode that corresponds to the given SocketError</returns>
-        public static ErrorCode ToErrorCode(this SocketError error)
-        {
-            switch (error)
-            {
-                case SocketError.AccessDenied:
-                    return ErrorCode.AccessDenied;
-                case SocketError.Fault:
-                    return ErrorCode.Fault;
-                case SocketError.InvalidArgument:
-                    return ErrorCode.Invalid;
-                case SocketError.TooManyOpenSockets:
-                    return ErrorCode.TooManyOpenSockets;
-                case SocketError.InProgress:
-                    return ErrorCode.TryAgain;
-                case SocketError.MessageSize:
-                    return ErrorCode.MessageSize;
-                case SocketError.ProtocolNotSupported:
-                    return ErrorCode.ProtocolNotSupported;
-                case SocketError.AddressFamilyNotSupported:
-                    return ErrorCode.AddressFamilyNotSupported;
-                case SocketError.AddressNotAvailable:
-                    return ErrorCode.AddressNotAvailable;
-                case SocketError.AddressAlreadyInUse:
-                    return ErrorCode.AddressAlreadyInUse;
-                case SocketError.NetworkDown:
-                    return ErrorCode.NetworkDown;
-                case SocketError.NetworkUnreachable:
-                    return ErrorCode.NetworkUnreachable;
-                case SocketError.NetworkReset:
-                    return ErrorCode.NetworkReset;
-                case SocketError.ConnectionAborted:
-                    return ErrorCode.ConnectionAborted;
-                case SocketError.ConnectionReset:
-                    return ErrorCode.ConnectionReset;
-                case SocketError.NoBufferSpaceAvailable:
-                    return ErrorCode.NoBufferSpaceAvailable;
-                case SocketError.NotConnected:
-                    return ErrorCode.NotConnected;
-                case SocketError.TimedOut:
-                    return ErrorCode.TimedOut;
-                case SocketError.ConnectionRefused:
-                    return ErrorCode.ConnectionRefused;
-                case SocketError.HostUnreachable:
-                    return ErrorCode.HostUnreachable;
-                default:
-                    Debug.Assert(false);
-                    return 0;
-            }
-        }
-    }
-}

+ 0 - 34
Communication/NetMQ/Core/HellloMsgSession.cs

@@ -1,34 +0,0 @@
-namespace NetMQ.Core
-{
-    class HelloMsgSession : SessionBase
-    {
-        bool m_newPipe;
-
-        public HelloMsgSession(IOThread ioThread, bool connect, SocketBase socket, Options options, Address addr) : 
-            base(ioThread, connect, socket, options, addr)
-        {
-            m_newPipe = true;
-        }
-
-        public override PullMsgResult PullMsg(ref Msg msg)
-        {
-            if (m_newPipe)
-            {
-                Assumes.NotNull(m_options.HelloMsg);
-
-                m_newPipe = false;
-                msg.InitPool(m_options.HelloMsg.Length);
-                msg.Put(m_options.HelloMsg, 0, m_options.HelloMsg.Length);
-                return PullMsgResult.Ok;
-            }
-
-            return base.PullMsg(ref msg);
-        }
-
-        protected override void Reset()
-        {
-            base.Reset();
-            m_newPipe = true;
-        }
-    }
-}

+ 0 - 11
Communication/NetMQ/Core/IMailbox.cs

@@ -1,11 +0,0 @@
-namespace NetMQ.Core
-{
-    internal interface IMailbox
-    {
-        void Send(Command command);
-
-        bool TryRecv(int timeout, out Command command);
-
-        void Close();
-    }
-}

+ 0 - 15
Communication/NetMQ/Core/IMsgSink.cs

@@ -1,15 +0,0 @@
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Interface IMsgSink mandates a PushMsg( Msg ) method.
-    /// </summary>
-    internal interface IMsgSink
-    {
-        /// <summary>
-        /// Deliver a message. Return true if successful; false otherwise.
-        /// This function takes ownership of the passed message.
-        /// </summary>
-        /// <param name="msg">the message (of type Msg) to deliver</param>
-        bool PushMsg(ref Msg msg);
-    }
-}

+ 0 - 17
Communication/NetMQ/Core/IMsgSource.cs

@@ -1,17 +0,0 @@
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Classes that implement IMsgSource are able to fetch a message, with the method: PullMsg.
-    /// </summary>
-    internal interface IMsgSource
-    {
-        /// <summary>
-        /// Fetch a message.
-        /// If successful - returns true and writes the message instance to the msg argument.
-        /// If not successful - return false and write null to the msg argument.
-        /// </summary>
-        /// <param name="msg">the Msg to write the fetched message into</param>
-        /// <returns>true if successful - and writes the message to the msg argument</returns>
-        bool PullMsg(ref Msg msg);
-    }
-}

+ 0 - 149
Communication/NetMQ/Core/IOObject.cs

@@ -1,149 +0,0 @@
-/*
-    Copyright (c) 2009-2011 250bpm s.r.o.
-    Copyright (c) 2007-2009 iMatix Corporation
-    Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using System.Diagnostics;
-using System.Net.Sockets;
-using AsyncIO;
-
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Simple base class for objects that live in I/O threads.
-    /// It makes communication with the poller object easier and
-    /// makes defining unneeded event handlers unnecessary.
-    /// </summary>
-    internal class IOObject : IProactorEvents
-    {
-        private IOThread? m_ioThread;
-        private IProactorEvents? m_handler;
-
-        /// <summary>
-        /// Create a new IOObject object and plug it into the given IOThread.
-        /// </summary>
-        /// <param name="ioThread">the IOThread to plug this new IOObject into.</param>
-        public IOObject(IOThread? ioThread)
-        {
-            if (ioThread != null)
-                Plug(ioThread);
-        }
-
-        /// <summary>
-        /// "Plug in" this IOObject to the given IOThread, - ie associate this with the specified IOThread.
-        /// </summary>
-        /// <param name="ioThread">the IOThread for this object to live in</param>
-        /// <remarks>
-        /// When migrating an object from one I/O thread to another, first
-        /// unplug it, then migrate it, then plug it to the new thread.
-        /// </remarks>
-        public void Plug(IOThread ioThread)
-        {
-            Debug.Assert(ioThread != null);
-
-            m_ioThread = ioThread;
-        }
-
-        /// <summary>
-        /// "Un-Plug" this IOObject from its current IOThread, and set its handler to null.
-        /// </summary>
-        /// <remarks>
-        /// When migrating an object from one I/O thread to another, first
-        /// unplug it, then migrate it, then plug it to the new thread.
-        /// </remarks>
-        public void Unplug()
-        {
-            Assumes.NotNull(m_ioThread);
-
-            // Forget about old poller in preparation to be migrated
-            // to a different I/O thread.
-            m_ioThread = null;
-            m_handler = null;
-        }
-
-        /// <summary>
-        /// Add the given socket to the Proactor.
-        /// </summary>
-        /// <param name="socket">the AsyncSocket to add</param>
-        public void AddSocket(AsyncSocket socket)
-        {
-            Assumes.NotNull(m_ioThread);
-            m_ioThread.Proactor.AddSocket(socket, this);
-        }
-
-        /// <summary>
-        /// Remove the given socket from the Proactor.
-        /// </summary>
-        /// <param name="socket">the AsyncSocket to remove</param>
-        public void RemoveSocket(AsyncSocket socket)
-        {
-            Assumes.NotNull(m_ioThread);
-            m_ioThread.Proactor.RemoveSocket(socket);
-        }
-
-        /// <summary>
-        /// This method is called when a message receive operation has been completed. This forwards it on to the handler's InCompleted method.
-        /// </summary>
-        /// <param name="socketError">a SocketError value that indicates whether Success or an error occurred</param>
-        /// <param name="bytesTransferred">the number of bytes that were transferred</param>
-        public virtual void InCompleted(SocketError socketError, int bytesTransferred)
-        {
-            Assumes.NotNull(m_handler);
-            m_handler.InCompleted(socketError, bytesTransferred);
-        }
-
-        /// <summary>
-        /// This method is called when a message Send operation has been completed. This forwards it on to the handler's OutCompleted method.
-        /// </summary>
-        /// <param name="socketError">a SocketError value that indicates whether Success or an error occurred</param>
-        /// <param name="bytesTransferred">the number of bytes that were transferred</param>
-        public virtual void OutCompleted(SocketError socketError, int bytesTransferred)
-        {
-            Assumes.NotNull(m_handler);
-            m_handler.OutCompleted(socketError, bytesTransferred);
-        }
-
-        /// <summary>
-        /// This is called when the timer expires.
-        /// </summary>
-        /// <param name="id">an integer used to identify the timer</param>
-        public virtual void TimerEvent(int id)
-        {
-            Assumes.NotNull(m_handler);
-            m_handler.TimerEvent(id);
-        }
-
-        public void AddTimer(long timeout, int id)
-        {
-            Assumes.NotNull(m_ioThread);
-            m_ioThread.Proactor.AddTimer(timeout, this, id);
-        }
-
-        public void SetHandler(IProactorEvents handler)
-        {
-            m_handler = handler;
-        }
-
-        public void CancelTimer(int id)
-        {
-            Assumes.NotNull(m_ioThread);
-            m_ioThread.Proactor.CancelTimer(this, id);
-        }
-    }
-}

+ 0 - 106
Communication/NetMQ/Core/IOThread.cs

@@ -1,106 +0,0 @@
-/*
-    Copyright (c) 2009-2011 250bpm s.r.o.
-    Copyright (c) 2007-2009 iMatix Corporation
-    Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using NetMQ.Core.Utils;
-
-namespace NetMQ.Core
-{
-    internal sealed class IOThread : ZObject, IMailboxEvent
-    {
-        /// <summary>
-        /// I/O thread accesses incoming commands via this mailbox.
-        /// </summary>
-        private readonly IOThreadMailbox m_mailbox;
-
-        /// <summary>
-        /// I/O multiplexing is performed using a poller object.
-        /// </summary>
-        private readonly Proactor m_proactor;
-
-#if DEBUG
-        /// <summary>
-        /// This gets set to "iothread-" plus the thread-id.
-        /// </summary>
-        private readonly string m_name;
-#endif
-
-        /// <summary>
-        /// Create a new IOThread object within the given context (Ctx) and thread.
-        /// </summary>
-        /// <param name="ctx">the Ctx (context) for this thread to live within</param>
-        /// <param name="threadId">the integer thread-id for this new IOThread</param>
-        public IOThread(Ctx ctx, int threadId)
-            : base(ctx, threadId)
-        {
-            var name = "iothread-" + threadId;
-            m_proactor = new Proactor(name);
-            m_mailbox = new IOThreadMailbox(name, m_proactor, this);
-
-#if DEBUG
-            m_name = name;
-#endif
-        }
-
-        internal Proactor Proactor => m_proactor;
-
-        public void Start()
-        {
-            m_proactor.Start();
-        }
-
-        public void Destroy()
-        {
-            m_proactor.Destroy();
-            m_mailbox.Close();
-        }
-
-        public void Stop()
-        {
-            SendStop();
-        }
-
-        public IMailbox Mailbox => m_mailbox;
-
-        public int Load => m_proactor.Load;
-
-        protected override void ProcessStop()
-        {
-            m_proactor.Stop();
-        }
-
-        public void Ready()
-        {
-            // Process all available commands.
-            while (m_mailbox.TryRecv(out Command command))
-            {
-                Assumes.NotNull(command.Destination);
-                command.Destination.ProcessCommand(command);
-            }
-        }
-
-#if DEBUG
-        public override string ToString()
-        {
-            return base.ToString() + "[" + m_name + "]";
-        }
-#endif
-    }
-}

+ 0 - 39
Communication/NetMQ/Core/IPollEvents.cs

@@ -1,39 +0,0 @@
-/*
-    Copyright (c) 2009-2011 250bpm s.r.o.
-    Copyright (c) 2007-2009 iMatix Corporation
-    Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// Classes that implement IPollEvents provide two methods (InEvent and OutEvent) that are invoked when ready for reading or writing.
-    /// </summary>
-    internal interface IPollEvents : ITimerEvent
-    {
-        /// <summary>
-        /// Called by the I/O thread when the file descriptor is ready for reading.
-        /// </summary>
-        void InEvent();
-
-        /// <summary>
-        /// Called by the I/O thread when the file descriptor is ready for writing.
-        /// </summary>
-        void OutEvent();
-    }
-}

+ 0 - 46
Communication/NetMQ/Core/IProactorEvents.cs

@@ -1,46 +0,0 @@
-/*
-    Copyright (c) 2009-2011 250bpm s.r.o.
-    Copyright (c) 2007-2009 iMatix Corporation
-    Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using System.Net.Sockets;
-
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// This is an ITimerEvent, with InCompleted and OutCompleted callback-methods,
-    /// used for implementing a Proactor pattern.
-    /// </summary>
-    internal interface IProactorEvents : ITimerEvent
-    {
-        /// <summary>
-        /// This is the "Input-Completed" method - called by the I/O-thread when the file descriptor is ready for reading.
-        /// </summary>
-        /// <param name="socketError">this is set to any socket-error that has occurred</param>
-        /// <param name="bytesTransferred">the number of bytes that are now ready to be read</param>
-        void InCompleted(SocketError socketError, int bytesTransferred);
-
-        /// <summary>
-        /// This is the "Output-Completed" method - called by the I/O thread when the file descriptor is ready for writing.
-        /// </summary>
-        /// <param name="socketError">this is set to any socket-error that has occurred</param>
-        /// <param name="bytesTransferred">the number of bytes that are now ready to be written</param>
-        void OutCompleted(SocketError socketError, int bytesTransferred);
-    }
-}

+ 0 - 15
Communication/NetMQ/Core/ITimerEvent.cs

@@ -1,15 +0,0 @@
-namespace NetMQ.Core
-{
-    /// <summary>
-    /// The ITimerEvent interface mandates a TimerEvent( int id ) method,
-    /// that is called with an id-value when the timer expires.
-    /// </summary>
-    internal interface ITimerEvent
-    {
-        /// <summary>
-        /// This is called when the timer expires.
-        /// </summary>
-        /// <param name="id">an integer used to identify the timer</param>
-        void TimerEvent(int id);
-    }
-}

+ 0 - 260
Communication/NetMQ/Core/Mailbox.cs

@@ -1,260 +0,0 @@
-/*
-    Copyright (c) 2010-2011 250bpm s.r.o.
-    Copyright (c) 2007-2009 iMatix Corporation
-    Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
-
-    This file is part of 0MQ.
-
-    0MQ is free software; you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    0MQ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using System;
-using System.Diagnostics;
-using System.Net.Sockets;
-using NetMQ.Core.Utils;
-
-namespace NetMQ.Core
-{
-    internal interface IMailboxEvent
-    {
-        void Ready();
-    }
-
-    internal class IOThreadMailbox : IMailbox
-    {
-        private readonly Proactor m_proactor;
-
-        private readonly IMailboxEvent m_mailboxEvent;
-
-        private readonly YPipe<Command> m_commandPipe = new YPipe<Command>(Config.CommandPipeGranularity, "mailbox");
-
-        /// <summary>
-        /// There's only one thread receiving from the mailbox, but there
-        /// is arbitrary number of threads sending. Given that ypipe requires
-        /// synchronised access on both of its endpoints, we have to synchronize
-        /// the sending side.
-        /// </summary>
-        private readonly object m_sync = new object();
-
-#if DEBUG
-        /// <summary>Mailbox name. Only used for debugging.</summary>
-        private readonly string m_name;
-#endif
-
-        private bool m_disposed;
-
-        public IOThreadMailbox(string name, Proactor proactor, IMailboxEvent mailboxEvent)
-        {
-            m_proactor = proactor;
-            m_mailboxEvent = mailboxEvent;
-
-            // Get the pipe into passive state. That way, if the users starts by
-            // polling on the associated file descriptor it will get woken up when
-            // new command is posted.
-            bool ok = m_commandPipe.TryRead(out Command cmd);
-            Debug.Assert(!ok);
-
-#if DEBUG
-            m_name = name;
-#endif
-        }
-
-        public void Send(Command command)
-        {
-            bool ok;
-            lock (m_sync)
-            {
-                m_commandPipe.Write(ref command, false);
-                ok = m_commandPipe.Flush();
-            }
-
-            if (!ok)
-            {
-                m_proactor.SignalMailbox(this);
-            }
-        }
-
-        public bool TryRecv(int timeout, out Command command)
-        {
-            throw new System.NotImplementedException();
-        }
-
-        public bool TryRecv(out Command command)
-        {
-            return m_commandPipe.TryRead(out command);
-        }
-        
-        public void RaiseEvent()
-        {
-            if (!m_disposed)
-            {
-                m_mailboxEvent.Ready();
-            }
-        }
-
-        public void Close()
-        {
-            m_disposed = true;
-        }
-
-#if DEBUG
-        public override string ToString()
-        {
-            return base.ToString() + "[" + m_name + "]";
-        }
-#endif
-    }
-
-    internal class Mailbox : IMailbox
-    {
-        /// <summary>
-        /// The pipe to store actual commands.
-        /// </summary>
-        private readonly YPipe<Command> m_commandPipe = new YPipe<Command>(Config.CommandPipeGranularity, "mailbox");
-
-        /// <summary>
-        /// Signaler to pass signals from writer thread to reader thread.
-        /// </summary>
-        private readonly Signaler m_signaler = new Signaler();
-
-        /// <summary>
-        /// There's only one thread receiving from the mailbox, but there
-        /// is an arbitrary number of threads sending. Given that <see cref="YPipe{T}"/> requires
-        /// synchronised access on both of its endpoints, we have to synchronize
-        /// the sending side.
-        /// </summary>
-        private readonly object m_sync = new object();
-
-        /// <summary>
-        /// True if the underlying pipe is active, ie. when we are allowed to
-        /// read commands from it.
-        /// </summary>
-        private bool m_active;
-
-#if DEBUG
-        /// <summary>Mailbox name. Only used for debugging.</summary>
-        private readonly string m_name;
-#endif
-
-        /// <summary>
-        /// Create a new Mailbox with the given name.
-        /// </summary>
-        /// <param name="name">the name to give this new Mailbox</param>
-        public Mailbox(string name)
-        {
-            // Get the pipe into passive state. That way, if the users starts by
-            // polling on the associated file descriptor it will get woken up when
-            // new command is posted.
-
-            bool ok = m_commandPipe.TryRead(out Command cmd);
-
-            //Debug.Assert(!ok);
-
-            m_active = false;
-
-#if DEBUG
-            m_name = name;
-#endif
-        }
-
-        /// <summary>
-        /// Get the socket-handle contained by the Signaler.
-        /// </summary>
-        public Socket Handle => m_signaler.Handle;
-
-        /// <summary>
-        /// Send the given Command out across the command-pipe.
-        /// </summary>
-        /// <param name="cmd">the Command to send</param>
-        public void Send(Command cmd)
-        {
-            bool ok;
-            lock (m_sync)
-            {
-                m_commandPipe.Write(ref cmd, false);
-                ok = m_commandPipe.Flush();
-            }
-
-            //if (LOG.isDebugEnabled())
-            //    LOG.debug( "{} -> {} / {} {}", new Object[] { Thread.currentThread().getName(), cmd_, cmd_.arg , !ok});
-
-            if (!ok)
-            {
-                m_signaler.Send();
-            }
-        }
-
-        /// <summary>
-        /// Receive and return a Command from the command-pipe.
-        /// </summary>
-        /// <param name="timeout">how long to wait for a command (in milliseconds) before returning</param>
-        /// <param name="command"></param>
-        public bool TryRecv(int timeout, out Command command)
-        {
-            // Try to get the command straight away.
-            if (m_active)
-            {
-                if (m_commandPipe.TryRead(out command))
-                    return true;
-
-                // If there are no more commands available, switch into passive state.
-                try
-                {
-                    m_active = false;
-                    m_signaler.Recv();
-                }
-                catch
-                {
-                    m_active = true;
-                    command = default(Command);
-                    return false;
-                }
-            }
-
-            // Wait for signal from the command sender.
-            if (!m_signaler.WaitEvent(timeout))
-            {
-                command = default(Command);
-                return false;
-            }
-
-            // We've got the signal. Now we can switch into active state.
-            m_active = true;
-
-            // Get a command.
-            var ok = m_commandPipe.TryRead(out command);
-           // Debug.Assert(ok);
-            return ok;
-        }
-
-        /// <summary>
-        /// Close the contained Signaler.
-        /// </summary>
-        public void Close()
-        {
-            m_signaler.Close();
-        }
-
-#if DEBUG
-        /// <summary>
-        /// Override ToString to provide the type-name, plus the Mailbox name within brackets.
-        /// </summary>
-        /// <returns>a string of the form Mailbox[name]</returns>
-        public override string ToString()
-        {
-            return base.ToString() + "[" + m_name + "]";
-        }
-#endif
-    }
-}

+ 0 - 119
Communication/NetMQ/Core/MailboxSafe.cs

@@ -1,119 +0,0 @@
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using NetMQ.Core.Utils;
-
-namespace NetMQ.Core
-{
-    internal class MailboxSafe : IMailbox
-    {
-        /// <summary>
-        /// The pipe to store actual commands.
-        /// </summary>
-        private readonly YPipe<Command> m_commandPipe = new YPipe<Command>(Config.CommandPipeGranularity, "mailbox");
-
-        //  Synchronize access to the mailbox from receivers and senders
-        private object m_sync;
-
-        private List<Signaler> m_signalers = new List<Signaler>();
-
-#if DEBUG
-        /// <summary>Mailbox name. Only used for debugging.</summary>
-        private readonly string m_name;
-#endif
-
-        /// <summary>
-        /// Create a new MailboxSafe with the given name.
-        /// </summary>
-        /// <param name="name">the name to give this new Mailbox</param>
-        /// <param name="sync">Synchronize access to the mailbox from receivers and senders</param>
-        public MailboxSafe(string name, object sync)
-        {
-            m_sync = sync;
-
-            // Get the pipe into passive state. That way, if the users starts by
-            // polling on the associated file descriptor it will get woken up when
-            // new command is posted.
-            bool ok = m_commandPipe.TryRead(out Command cmd);
-            Debug.Assert(!ok);
-
-#if DEBUG
-            m_name = name;
-#endif
-        }
-
-        public void AddSignaler(Signaler signaler)
-        {
-            m_signalers.Add(signaler);
-        }
-
-        public void RemoveSignaler(Signaler signaler)
-        {
-            m_signalers.Remove(signaler);
-        }
-
-        public void ClearSignalers()
-        {
-            m_signalers.Clear();
-        }
-
-        public void Send(Command cmd)
-        {
-            lock (m_sync)
-            {
-                m_commandPipe.Write(ref cmd, false);
-                bool ok = m_commandPipe.Flush();
-
-                if (!ok)
-                {
-                    Monitor.PulseAll(m_sync);
-
-                    foreach (var signaler in m_signalers)
-                    {
-                        signaler.Send();
-                    }
-                }
-            }
-        }
-
-        public bool TryRecv(int timeout, out Command command)
-        {
-            //  Try to get the command straight away.
-            if (m_commandPipe.TryRead(out command))
-                return true;
-
-            //  If the timeout is zero, it will be quicker to release the lock, giving other a chance to send a command
-            //  and immediately relock it.
-            if (timeout == 0)
-            {
-                Monitor.Exit(m_sync);
-                Monitor.Enter(m_sync);
-            }
-            else
-            {
-                //  Wait for signal from the command sender.
-                Monitor.Wait(m_sync, timeout);
-            }
-
-            //  Another thread may already fetch the command
-            return m_commandPipe.TryRead(out command);
-        }
-
-        public void Close()
-        {
-            Monitor.Enter(m_sync);
-            Monitor.Exit(m_sync);
-        }
-
-#if DEBUG
-        /// <summary>
-        /// Override ToString to provide the type-name, plus the Mailbox name within brackets.
-        /// </summary>
-        /// <returns>a string of the form Mailbox[name]</returns>
-        public override string ToString()
-        {
-            return base.ToString() + "[" + m_name + "]";
-        }
-#endif
-    }
-}

+ 0 - 279
Communication/NetMQ/Core/Mechanisms/CurveClientMechanism.cs

@@ -1,279 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Security.Cryptography;
-using System.Text;
-using NaCl;
-
-namespace NetMQ.Core.Mechanisms
-{
-    internal class CurveClientMechanism : CurveMechanismBase
-    {
-        enum State
-        {
-            SendHello,
-            ExpectWelcome,
-            SendInitiate,
-            ExpectReady,
-            ErrorReceived,
-            Connected
-        };
-
-        private byte[] m_secretKey;
-        private byte[] m_publicKey;
-        private byte[] m_serverKey;
-
-        private byte[] m_cnSecretKey;
-        private byte[] m_cnPublicKey;
-        private byte[]? m_cnServerKey;
-        private byte[]? m_cnCookie;
-
-        private State m_state;
-
-        public CurveClientMechanism(SessionBase session, Options options) :
-            base(session, options, "CurveZMQMESSAGEC", "CurveZMQMESSAGES")
-        {
-            m_secretKey = (byte[]) options.CurveSecretKey.Clone();
-            m_publicKey = (byte[]) options.CurvePublicKey.Clone();
-            m_serverKey = (byte[]) options.CurveServerKey.Clone();
-            Curve25519XSalsa20Poly1305.KeyPair(out m_cnSecretKey, out m_cnPublicKey);
-        }
-
-        public override void Dispose()
-        {
-            base.Dispose();
-            Array.Clear(m_secretKey, 0, 32);
-            Array.Clear(m_publicKey, 0, 32);
-            Array.Clear(m_serverKey, 0, 32);
-            Array.Clear(m_cnSecretKey, 0, 32);
-            Array.Clear(m_cnPublicKey, 0, 32);
-        }
-
-        public override MechanismStatus Status
-        {
-            get
-            {
-                if (m_state == State.Connected)
-                    return MechanismStatus.Ready;
-                if (m_state == State.ErrorReceived)
-                    return MechanismStatus.Error;
-
-                return MechanismStatus.Handshaking;
-            }
-        }
-
-        public override PullMsgResult NextHandshakeCommand(ref Msg msg)
-        {
-            PullMsgResult result = 0;
-
-            switch (m_state)
-            {
-                case State.SendHello:
-                    result = ProduceHello(ref msg);
-                    if (result == PullMsgResult.Ok)
-                        m_state = State.ExpectWelcome;
-                    break;
-                case State.SendInitiate:
-                    result = ProduceInitiate(ref msg);
-                    if (result == 0)
-                        m_state = State.ExpectReady;
-                    break;
-                default:
-                    result = PullMsgResult.Empty;
-                    break;
-            }
-
-            return result;
-        }
-
-        public override PushMsgResult ProcessHandshakeCommand(ref Msg msg)
-        {
-            PushMsgResult result;
-
-            if (IsCommand("WELCOME", ref msg))
-                result = ProcessWelcome(ref msg);
-            else if (IsCommand("READY", ref msg))
-                result = ProcessReady(ref msg);
-            else if (IsCommand("ERROR", ref msg))
-                result = ProcessError(ref msg);
-            else
-                result = PushMsgResult.Error;
-
-            if (result == PushMsgResult.Ok)
-            {
-                msg.Close();
-                msg.InitEmpty();
-            }
-
-            return result;
-        }
-
-        PullMsgResult ProduceHello(ref Msg msg)
-        {
-            msg.InitPool(200);
-
-            Span<byte> helloNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            Span<byte> helloPlaintext = stackalloc byte[64];
-            Span<byte> helloBox = msg.Slice(120);
-
-            // Prepare the full nonce
-            HelloNoncePrefix.CopyTo(helloNonce);
-            NetworkOrderBitsConverter.PutUInt64(m_nonce, helloNonce.Slice(16));
-
-            // Create Box [64 * %x0](C'->S)
-            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_serverKey);
-            box.Encrypt(helloBox, helloPlaintext, helloNonce);
-
-            Span<byte> hello = msg;
-
-            HelloLiteral.CopyTo(hello);
-            
-            //  CurveZMQ major and minor version numbers
-            hello[6] = 1;
-            hello[7] = 0;
-
-            // 8-80 are left zeros for anti-amplification padding
-
-            //  Client public connection key
-            m_cnPublicKey.CopyTo(hello.Slice(80));
-
-            //  Short nonce, prefixed by "CurveZMQHELLO---"
-            helloNonce.Slice(16).CopyTo(hello.Slice(112));
-
-            m_nonce++;
-
-            return PullMsgResult.Ok;
-        }
-
-        PushMsgResult ProcessWelcome(ref Msg msg)
-        {
-            if (msg.Size != 168)
-                return PushMsgResult.Error;
-
-            Span<byte> welcomeNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            Span<byte> welcomePlaintext = stackalloc byte[128];
-            Span<byte> welcomeBox = msg.Slice(24, 144);
-
-            WelcomeNoncePrefix.CopyTo(welcomeNonce);
-            msg.Slice(8, 16).CopyTo(welcomeNonce.Slice(8));
-
-            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_serverKey);
-            bool isDecrypted = box.TryDecrypt(welcomePlaintext, welcomeBox, welcomeNonce);
-            if (!isDecrypted)
-                return PushMsgResult.Error;
-
-            m_cnServerKey = welcomePlaintext.Slice(0, 32).ToArray();
-            m_cnCookie = welcomePlaintext.Slice(32, 16 + 80).ToArray();
-
-            // Create the curve box
-            m_box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnServerKey);
-
-            m_state = State.SendInitiate;
-
-            return PushMsgResult.Ok;
-        }
-
-        PullMsgResult ProduceInitiate(ref Msg msg)
-        {
-            int metadataLength = BasicPropertiesLength;
-            byte[] metadataPlaintext = new byte[metadataLength];
-            AddBasicProperties(metadataPlaintext);
-            msg.InitPool(113 + 128 + metadataLength + Curve25519XSalsa20Poly1305.TagLength);
-
-            Span<byte> vouchNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            Span<byte> vouchPlaintext = stackalloc byte[64];
-            Span<byte> vouchBox = stackalloc byte[Curve25519XSalsa20Poly1305.TagLength + 64];
-
-            //  Create vouch = Box [C',S](C->S')
-            m_cnPublicKey.CopyTo(vouchPlaintext);
-            m_serverKey.CopyTo(vouchPlaintext.Slice(32));
-
-            VouchNoncePrefix.CopyTo(vouchNonce);
-            using var rng = RandomNumberGenerator.Create();
-#if NETSTANDARD2_1
-            rng.GetBytes(vouchNonce.Slice(8));
-#else
-            byte[] temp = new byte[16];
-            rng.GetBytes(temp);
-            temp.CopyTo(vouchNonce.Slice(8));
-#endif
-
-            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnServerKey);
-            box.Encrypt(vouchBox, vouchPlaintext, vouchNonce);
-
-            Span<byte> initiate = msg;
-            Span<byte> initiateNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            Span<byte> initiatePlaintext = new byte[128 + metadataLength];
-            Span<byte> initiateBox = initiate.Slice(113);
-
-            //  Create Box [C + vouch + metadata](C'->S')
-            m_publicKey.CopyTo(initiatePlaintext);
-            vouchNonce.Slice(8).CopyTo(initiatePlaintext.Slice(32));
-            vouchBox.CopyTo(initiatePlaintext.Slice(48));
-            metadataPlaintext.CopyTo(initiatePlaintext.Slice(48 + 80));
-            Array.Clear(metadataPlaintext, 0, metadataPlaintext.Length);
-
-            InitiatieNoncePrefix.CopyTo(initiateNonce);
-            NetworkOrderBitsConverter.PutUInt64(m_nonce, initiateNonce.Slice(16));
-
-            using var box2 = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnServerKey);
-            box2.Encrypt(initiateBox, initiatePlaintext, initiateNonce);
-            
-            InitiateLiteral.CopyTo(initiate);
-
-            //  Cookie provided by the server in the WELCOME command
-            m_cnCookie.CopyTo(initiate.Slice(9, 96));
-
-            //  Short nonce, prefixed by "CurveZMQINITIATE"
-            initiateNonce.Slice(16).CopyTo(initiate.Slice(105));
-
-            m_nonce++;
-
-            return PullMsgResult.Ok;
-        }
-
-        PushMsgResult ProcessReady(ref Msg msg)
-        {
-            if (msg.Size < 30)
-                return PushMsgResult.Error;
-
-            Span<byte> readyNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            var readyPlaintext = new byte[msg.Size - 14 - Curve25519XSalsa20Poly1305.TagLength];
-            Span<byte> readyBox = msg.Slice(14);
-
-            ReadyNoncePrefix.CopyTo(readyNonce);
-            msg.Slice(6, 8).CopyTo(readyNonce.Slice(16));
-            m_peerNonce = NetworkOrderBitsConverter.ToUInt64(msg, 6);
-
-            Assumes.NotNull(m_box);
-
-            bool isDecrypted = m_box.TryDecrypt(readyPlaintext, readyBox, readyNonce);
-            if (!isDecrypted)
-                return PushMsgResult.Error;
-
-            if (!ParseMetadata(readyPlaintext))
-                return PushMsgResult.Error;
-            
-            Array.Clear(readyPlaintext, 0, readyPlaintext.Length);
-
-            m_state = State.Connected;
-            return PushMsgResult.Ok;
-        }
-        
-        PushMsgResult ProcessError(ref Msg msg)
-        {
-            if (m_state != State.ExpectWelcome && m_state != State.ExpectReady)
-                return PushMsgResult.Error;
-            
-            if (msg.Size < 7) 
-                return PushMsgResult.Error;;
-
-            int errorReasonLength = msg[6];
-            if (errorReasonLength > msg.Size - 7)
-                return PushMsgResult.Error;
-
-            string errorReason = msg.GetString(Encoding.ASCII, 7, errorReasonLength);
-            m_state = State.ErrorReceived;
-            return PushMsgResult.Ok;
-        }
-    }
-}

+ 0 - 129
Communication/NetMQ/Core/Mechanisms/CurveMechanismBase.cs

@@ -1,129 +0,0 @@
-using System;
-using System.Text;
-using NaCl;
-
-namespace NetMQ.Core.Mechanisms
-{
-    internal abstract class CurveMechanismBase : Mechanism
-    {
-        protected static byte[] HelloNoncePrefix = Encoding.ASCII.GetBytes("CurveZMQHELLO---");
-        protected static byte[] CookieNoncePrefix = Encoding.ASCII.GetBytes("COOKIE--");
-        protected static byte[] WelcomeNoncePrefix = Encoding.ASCII.GetBytes("WELCOME-");
-        protected static byte[] InitiatieNoncePrefix = Encoding.ASCII.GetBytes("CurveZMQINITIATE");
-        protected static byte[] VouchNoncePrefix = Encoding.ASCII.GetBytes("VOUCH---");
-        protected static byte[] ReadyNoncePrefix = Encoding.ASCII.GetBytes("CurveZMQREADY---");
-        protected static readonly byte[] WelcomeLiteral = Encoding.ASCII.GetBytes("\x07WELCOME");
-        protected static readonly byte[] ReadyLiteral = Encoding.ASCII.GetBytes("\x05READY");
-        protected static readonly byte[] HelloLiteral = Encoding.ASCII.GetBytes("\x05HELLO");
-        protected static readonly byte[] InitiateLiteral = Encoding.ASCII.GetBytes("\x08INITIATE");
-        private static readonly byte[] MessageLiteral = Encoding.ASCII.GetBytes("\x07MESSAGE");
-
-        private readonly byte[] m_encodeNoncePrefix;
-        private readonly byte[] m_decodeNoncePrefix;
-
-        protected UInt64 m_nonce;
-        protected UInt64 m_peerNonce;
-        protected Curve25519XSalsa20Poly1305? m_box;
-
-        protected CurveMechanismBase(SessionBase session, Options options,
-            string encodeNoncePrefix, string decodeNoncePrefix) : base(session, options)
-        {
-            m_encodeNoncePrefix = Encoding.ASCII.GetBytes(encodeNoncePrefix);
-            m_decodeNoncePrefix = Encoding.ASCII.GetBytes(decodeNoncePrefix);
-
-            if (m_encodeNoncePrefix.Length != 16)
-                throw new ArgumentException();
-
-            if (m_decodeNoncePrefix.Length != 16)
-                throw new ArgumentException();
-
-            m_nonce = 1;
-            m_peerNonce = 1;
-        }
-
-        public override void Dispose()
-        {
-            m_box?.Dispose();
-        }
-
-        public override PullMsgResult Encode(ref Msg msg)
-        {
-            Span<byte> messageNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            m_encodeNoncePrefix.CopyTo(messageNonce);
-            NetworkOrderBitsConverter.PutUInt64(m_nonce, messageNonce.Slice(16));
-
-            byte flags = 0;
-            if (msg.HasMore)
-                flags |= 0x01;
-            if (msg.HasCommand)
-                flags |= 0x02;
-
-            Msg plaintext = new Msg();
-            plaintext.InitPool(msg.Size + 1);
-            plaintext[0] = flags;
-            msg.CopyTo(plaintext.Slice(1));
-
-            msg.Close();
-            msg.InitPool(16 + Curve25519XSalsa20Poly1305.TagLength + plaintext.Size);
-
-
-            m_box.Encrypt(msg.Slice(16), plaintext, messageNonce);
-            plaintext.Close();
-
-            MessageLiteral.CopyTo(msg);
-            NetworkOrderBitsConverter.PutUInt64(m_nonce, msg.Slice(8));
-
-            m_nonce++;
-            return PullMsgResult.Ok;
-        }
-
-        public override PushMsgResult Decode(ref Msg msg)
-        {
-            if (!CheckBasicCommandStructure(ref msg))
-                return PushMsgResult.Error;
-
-            int size = msg.Size;
-
-            if (!IsCommand("MESSAGE", ref msg))
-                return PushMsgResult.Error;
-
-            if (size < 33) // Size of 16 bytes of command + 16 bytes of MAC + 1 byte for flag
-                return PushMsgResult.Error;
-
-            Span<byte> messageNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            m_decodeNoncePrefix.CopyTo(messageNonce);
-            msg.Slice(8,8).CopyTo(messageNonce.Slice(16));
-
-            UInt64 nonce = NetworkOrderBitsConverter.ToUInt64(msg, 8);
-            if (nonce <= m_peerNonce)
-                return PushMsgResult.Error;
-
-            m_peerNonce = nonce;
-
-            Msg plain = new Msg();
-            plain.InitPool(msg.Size - 16 - Curve25519XSalsa20Poly1305.TagLength);
-
-            Assumes.NotNull(m_box);
-
-            var isAuthenticate = m_box.TryDecrypt(plain,msg.Slice(16), messageNonce);
-
-            if (!isAuthenticate)
-            {
-                plain.Close();
-                return PushMsgResult.Error;
-            }
-
-            msg.Move(ref plain);
-
-            byte flags = msg[0];
-            if ((flags & 0x01) != 0)
-                msg.SetFlags(MsgFlags.More);
-            if ((flags & 0x02) != 0)
-                msg.SetFlags(MsgFlags.Command);
-
-            msg.TrimPrefix(1);
-
-            return PushMsgResult.Ok;
-        }
-    }
-}

+ 0 - 318
Communication/NetMQ/Core/Mechanisms/CurveServerMechanism.cs

@@ -1,318 +0,0 @@
-using System;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using NaCl;
-using NetMQ.Core.Utils;
-
-namespace NetMQ.Core.Mechanisms
-{
-    internal class CurveServerMechanism : CurveMechanismBase
-    {
-        protected enum State
-        {
-            WaitingForHello,
-            SendingWelcome,
-            SendingReady,
-            WaitingForInitiate,
-            Ready
-        }
-
-        private byte[] m_secretKey;
-        private byte[] m_cnSecretKey;
-        private byte[] m_cnPublicKey;
-        private byte[] m_cnClientKey;
-        private byte[] m_cookieKey;
-        private State m_state;
-
-        public CurveServerMechanism(SessionBase session, Options options) :
-            base(session, options, "CurveZMQMESSAGES", "CurveZMQMESSAGEC")
-        {
-            m_secretKey = (byte[]) options.CurveSecretKey.Clone();
-            m_cnClientKey = new byte[Curve25519XSalsa20Poly1305.KeyLength];
-            m_cookieKey = new byte[Curve25519XSalsa20Poly1305.KeyLength];
-            Curve25519XSalsa20Poly1305.KeyPair(out m_cnSecretKey, out m_cnPublicKey);
-        }
-        
-        public override void Dispose()
-        {
-            base.Dispose();
-            Array.Clear(m_secretKey, 0, 32);
-            Array.Clear(m_cnSecretKey, 0, 32);
-            Array.Clear(m_cnPublicKey, 0, 32);
-            Array.Clear(m_cnClientKey, 0, 32);
-            Array.Clear(m_cookieKey, 0, m_cookieKey.Length);
-        }
-
-        public override MechanismStatus Status
-        {
-            get
-            {
-                if (m_state == State.Ready)
-                    return MechanismStatus.Ready;
-                else
-                    return MechanismStatus.Handshaking;
-            }
-        }
-
-        public override PullMsgResult NextHandshakeCommand(ref Msg msg)
-        {
-            PullMsgResult result;
-
-            switch (m_state)
-            {
-                case State.SendingWelcome:
-                    result = ProduceWelcome(ref msg);
-                    if (result == PullMsgResult.Ok)
-                        m_state = State.WaitingForInitiate;
-                    break;
-                case State.SendingReady:
-                    result = ProduceReady(ref msg);
-                    if (result == PullMsgResult.Ok)
-                        m_state = State.Ready;
-                    break;
-                default:
-                    result = PullMsgResult.Empty;
-                    break;
-            }
-
-            return result;
-        }
-
-        public override PushMsgResult ProcessHandshakeCommand(ref Msg msg)
-        {
-            PushMsgResult result;
-
-            switch (m_state)
-            {
-                case State.WaitingForHello:
-                    result = ProcessHello(ref msg);
-                    break;
-                case State.WaitingForInitiate:
-                    result = ProcessInitiate(ref msg);
-                    break;
-                default:
-                    return PushMsgResult.Error;
-            }
-
-            if (result == PushMsgResult.Ok)
-            {
-                msg.Close();
-                msg.InitEmpty();
-            }
-
-            return result;
-        }
-
-        PushMsgResult ProcessHello(ref Msg msg)
-        {
-            if (!CheckBasicCommandStructure(ref msg))
-                return PushMsgResult.Error;
-
-            Span<byte> hello = msg;
-
-            if (!IsCommand("HELLO", ref msg))
-                return PushMsgResult.Error;
-
-            if (hello.Length != 200)
-                return PushMsgResult.Error;
-
-            byte major = hello[6];
-            byte minor = hello[7];
-
-            if (major != 1 || minor != 0)
-            {
-                // client HELLO has unknown version number
-                return PushMsgResult.Error;
-            }
-
-            // Save client's short-term public key (C')
-            hello.Slice(80, 32).CopyTo(m_cnClientKey);
-
-            Span<byte> helloNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            HelloNoncePrefix.CopyTo(helloNonce);
-            hello.Slice(112, 8).CopyTo(helloNonce.Slice(16));
-            m_peerNonce = NetworkOrderBitsConverter.ToUInt64(hello, 112);
-
-            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnClientKey);
-
-            Span<byte> helloPlaintext = stackalloc byte[80];
-            bool isDecrypted = box.TryDecrypt(helloPlaintext, hello.Slice(120, 80), helloNonce);
-            if (!isDecrypted)
-                return PushMsgResult.Error;
-
-            helloPlaintext.Clear();
-            
-            m_state = State.SendingWelcome;
-            return PushMsgResult.Ok;
-        }
-
-        PullMsgResult ProduceWelcome(ref Msg msg)
-        {
-            Span<byte> cookieNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            Span<byte> cookiePlaintext = stackalloc byte[64];
-            Span<byte> cookieCiphertext = stackalloc byte[64 + XSalsa20Poly1305.TagLength];
-
-            //  Create full nonce for encryption
-            //  8-byte prefix plus 16-byte random nonce
-            CookieNoncePrefix.CopyTo(cookieNonce);
-            using var rng = RandomNumberGenerator.Create();
-#if NETSTANDARD2_1
-            rng.GetBytes(cookieNonce.Slice(8));
-#else
-            byte[] temp = new byte[16];
-            rng.GetBytes(temp);
-            temp.CopyTo(cookieNonce.Slice(8));
-#endif
-
-            // Generate cookie = Box [C' + s'](t)
-            m_cnClientKey.CopyTo(cookiePlaintext);
-            m_cnSecretKey.CopyTo(cookiePlaintext.Slice(32));
-
-            // Generate fresh cookie key
-            rng.GetBytes(m_cookieKey);
-
-            // Encrypt using symmetric cookie key
-            using var secretBox = new XSalsa20Poly1305(m_cookieKey);
-            secretBox.Encrypt(cookieCiphertext, cookiePlaintext, cookieNonce);
-            cookiePlaintext.Clear();
-
-            Span<byte> welcomeNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            Span<byte> welcomePlaintext = stackalloc byte[128];
-            Span<byte> welcomeCiphertext = stackalloc byte[128 + Curve25519XSalsa20Poly1305.TagLength];
-
-            //  Create full nonce for encryption
-            //  8-byte prefix plus 16-byte random nonce
-            WelcomeNoncePrefix.CopyTo(welcomeNonce);
-#if NETSTANDARD2_1
-            rng.GetBytes(welcomeNonce.Slice(8));
-#else
-            rng.GetBytes(temp);
-            temp.CopyTo(welcomeNonce.Slice(8));
-#endif
-
-            // Create 144-byte Box [S' + cookie](S->C')
-            m_cnPublicKey.CopyTo(welcomePlaintext);
-            cookieNonce.Slice(8).CopyTo(welcomePlaintext.Slice(32));
-            cookieCiphertext.CopyTo(welcomePlaintext.Slice(48));
-            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnClientKey);
-            box.Encrypt(welcomeCiphertext, welcomePlaintext, welcomeNonce);
-            welcomePlaintext.Clear();
-
-            msg.InitPool(168); // TODO: we can save some allocation here by allocating this earlier
-            Span<byte> welcome = msg;
-            WelcomeLiteral.CopyTo(welcome);
-            welcomeNonce.Slice(8, 16).CopyTo(welcome.Slice(8));
-            welcomeCiphertext.CopyTo(welcome.Slice(24));
-
-            return PullMsgResult.Ok;
-        }
-
-        PushMsgResult ProcessInitiate(ref Msg msg)
-        {
-            if (!CheckBasicCommandStructure(ref msg))
-                return PushMsgResult.Error;
-
-            Span<byte> initiate = msg;
-
-            if (!IsCommand("INITIATE", ref msg))
-                return PushMsgResult.Error;
-
-            if (initiate.Length < 257)
-                return PushMsgResult.Error;
-
-            Span<byte> cookieNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            Span<byte> cookiePlaintext = stackalloc byte[64];
-            Span<byte> cookieBox = initiate.Slice(25, 80);
-
-            CookieNoncePrefix.CopyTo(cookieNonce);
-            initiate.Slice(9, 16).CopyTo(cookieNonce.Slice(8));
-
-            using var secretBox = new XSalsa20Poly1305(m_cookieKey);
-            bool decrypted = secretBox.TryDecrypt(cookiePlaintext, cookieBox, cookieNonce);
-
-            if (!decrypted)
-                return PushMsgResult.Error;
-
-            //  Check cookie plain text is as expected [C' + s']
-            if (!SpanUtility.Equals(m_cnClientKey, cookiePlaintext.Slice(0, 32)) ||
-                !SpanUtility.Equals(m_cnSecretKey, cookiePlaintext.Slice(32, 32)))
-                return PushMsgResult.Error;
-
-            Span<byte> initiateNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            byte[] initiatePlaintext = new byte[msg.Size - 113];
-            var initiateBox = initiate.Slice(113);
-
-            InitiatieNoncePrefix.CopyTo(initiateNonce);
-            initiate.Slice(105, 8).CopyTo(initiateNonce.Slice(16));
-            m_peerNonce = NetworkOrderBitsConverter.ToUInt64(initiate, 105);
-
-            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnClientKey);
-            bool decrypt = box.TryDecrypt(initiatePlaintext, initiateBox, initiateNonce);
-            if (!decrypt)
-                return PushMsgResult.Error;
-            
-            Span<byte> vouchNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            Span<byte> vouchPlaintext = stackalloc byte[64];
-            Span<byte> vouchBox = new Span<byte>(initiatePlaintext, 48, 80);
-            var clientKey = new Span<byte>(initiatePlaintext, 0, 32);
-
-            VouchNoncePrefix.CopyTo(vouchNonce);
-            new Span<byte>(initiatePlaintext, 32, 16).CopyTo(vouchNonce.Slice(8));
-
-            using var box2 = new Curve25519XSalsa20Poly1305(m_cnSecretKey, clientKey);
-            decrypt = box2.TryDecrypt(vouchPlaintext, vouchBox, vouchNonce);
-            if (!decrypt)
-                return PushMsgResult.Error;
-
-            //  What we decrypted must be the client's short-term public key
-            if (!SpanUtility.Equals(vouchPlaintext.Slice(0, 32), m_cnClientKey))
-                return PushMsgResult.Error;
-
-            //  Create the session box
-            m_box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnClientKey);
-
-            //  This supports the Stonehouse pattern (encryption without authentication).
-            m_state = State.SendingReady;
-
-            if (!ParseMetadata(new Span<byte>(initiatePlaintext, 128, initiatePlaintext.Length - 128 - 16)))
-                return PushMsgResult.Error;
-            
-            vouchPlaintext.Clear();
-            Array.Clear(initiatePlaintext, 0, initiatePlaintext.Length);
-
-            return PushMsgResult.Ok;
-        }
-
-        PullMsgResult ProduceReady(ref Msg msg)
-        {
-            int metadataLength = BasicPropertiesLength;
-            Span<byte> readyNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
-            byte[] readyPlaintext = new byte[metadataLength];
-
-            //  Create Box [metadata](S'->C')
-            AddBasicProperties(readyPlaintext);
-
-            ReadyNoncePrefix.CopyTo(readyNonce);
-            NetworkOrderBitsConverter.PutUInt64(m_nonce, readyNonce.Slice(16));
-
-            msg.InitPool(14 + Curve25519XSalsa20Poly1305.TagLength + metadataLength);
-            var readyBox = msg.Slice(14);
-
-            Assumes.NotNull(m_box);
-            
-            m_box.Encrypt(readyBox, readyPlaintext, readyNonce);
-            Array.Clear(readyPlaintext, 0, readyPlaintext.Length);
-            
-            Span<byte> ready = msg;
-            ReadyLiteral.CopyTo(ready);
-
-            //  Short nonce, prefixed by "CurveZMQREADY---"
-            readyNonce.Slice(16).CopyTo(ready.Slice(6));
-
-            m_nonce++;
-
-            return 0;
-        }
-    }
-}

+ 0 - 360
Communication/NetMQ/Core/Mechanisms/Mechanism.cs

@@ -1,360 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text;
-using NetMQ.Core.Utils;
-using NetMQ.Utils;
-
-namespace NetMQ.Core.Mechanisms
-{
-    internal enum MechanismStatus 
-    {
-        Handshaking,
-        Ready,
-        Error
-    }
-
-    internal abstract class Mechanism : IDisposable
-    {
-        static class SocketNames
-        {
-            public const string Pair = "PAIR";
-            public const string Pub = "PUB";
-            public const string Sub = "SUB";
-            public const string Req = "REQ";
-            public const string Rep = "REP";
-            public const string Dealer = "DEALER";
-            public const string Router = "ROUTER";
-            public const string Pull = "PULL";
-            public const string Push = "PUSH";
-            public const string Xpub = "XPUB";
-            public const string Xsub = "XSUB";
-            public const string Stream = "STREAM";    
-            public const string Peer = "PEER";
-            public const string Server = "SERVER";
-            public const string Client = "CLIENT";
-            public const string Radio = "RADIO";
-            public const string Dish = "DISH";
-            public const string Gather = "GATHER";
-            public const string Scatter = "SCATTER";
-        }
-        
-        const int NameLengthSize = sizeof(byte);
-        const int ValueLengthSize = sizeof(Int32);
-
-        private const string ZmtpPropertySocketType = "Socket-Type";
-        private const string ZmtpPropertyIdentity = "Identity";
-
-        public Mechanism(SessionBase session, Options options)
-        {
-            Session = session;
-            Options = options;
-        }
-        
-        /// <summary>
-        /// Prepare next handshake command that is to be sent to the peer.
-        /// </summary>
-        /// <param name="msg"></param>
-        /// <returns></returns>
-        public abstract PullMsgResult NextHandshakeCommand (ref Msg msg);
-
-        /// <summary>
-        /// Process the handshake command received from the peer.
-        /// </summary>
-        /// <param name="msg"></param>
-        /// <returns></returns>
-        public abstract PushMsgResult ProcessHandshakeCommand (ref Msg msg);
-
-        /// <summary>
-        /// Dispose the mechanism resources
-        /// </summary>
-        public abstract void Dispose();
-
-        public virtual PullMsgResult Encode(ref Msg msg)
-        {
-            return PullMsgResult.Ok;
-        }
-
-        public virtual PushMsgResult Decode(ref Msg msg)
-        {
-            return PushMsgResult.Ok;
-        }
-
-        /// <summary>
-        /// Returns the status of this mechanism.
-        /// </summary>
-        public abstract MechanismStatus Status { get; }
-        
-        public byte[]? PeerIdentity { get; set; }
-
-        public SessionBase Session { get; }
-        protected Options Options { get; }
-        
-        /// <summary>
-        ///  Only used to identify the socket for the Socket-Type
-        ///  property in the wire protocol. 
-        /// </summary>
-        /// <param name="socketType"></param>
-        protected string GetSocketName(ZmqSocketType socketType)
-        {
-            switch (socketType)
-            {
-                case ZmqSocketType.Pair:
-                    return SocketNames.Pair;
-                case ZmqSocketType.Pub:
-                    return SocketNames.Pub;
-                case ZmqSocketType.Sub:
-                    return SocketNames.Sub;
-                case ZmqSocketType.Req:
-                    return SocketNames.Req;
-                case ZmqSocketType.Rep:
-                    return SocketNames.Rep;
-                case ZmqSocketType.Dealer:
-                    return SocketNames.Dealer;
-                case ZmqSocketType.Router:
-                    return SocketNames.Router;
-                case ZmqSocketType.Pull:
-                    return SocketNames.Pull;
-                case ZmqSocketType.Push:
-                    return SocketNames.Push;
-                case ZmqSocketType.Xpub:
-                    return SocketNames.Xpub;
-                case ZmqSocketType.Xsub:
-                    return SocketNames.Xsub;
-                case ZmqSocketType.Stream:
-                    return SocketNames.Stream;
-                case ZmqSocketType.Peer:
-                    return SocketNames.Peer;
-                case ZmqSocketType.Server:
-                    return SocketNames.Server;
-                case ZmqSocketType.Client:
-                    return SocketNames.Client;
-                case ZmqSocketType.Radio:
-                    return SocketNames.Radio;
-                case ZmqSocketType.Dish:
-                    return SocketNames.Dish;
-                case ZmqSocketType.Gather:
-                    return SocketNames.Gather;
-                case ZmqSocketType.Scatter:
-                    return SocketNames.Scatter;
-                default:
-                    throw new ArgumentOutOfRangeException(nameof(socketType), socketType, null);
-            }
-        }
-        
-        protected int AddProperty(Span<byte> output, string name, byte[] value)
-        {
-            if (name.Length > 255)
-                throw new ArgumentException("property name length exceed maximum size");
-            
-            int totalLength =  GetPropertyLength(name, value.Length);
-            if (totalLength > output.Length)
-                throw new Exception("totalLength of property exceed maximum size");
-
-            output[0] = (byte) name.Length;
-            output = output.Slice(NameLengthSize);
-            System.Text.Encoding.ASCII.GetBytes(name, output);
-            output = output.Slice(name.Length);
-            NetworkOrderBitsConverter.PutInt32(value.Length, output);
-            output = output.Slice(ValueLengthSize);
-            value.CopyTo(output);
-            
-            return totalLength;
-        }
-
-        protected int AddProperty(Span<byte> output, string name, string value)
-        {
-            return AddProperty(output, name, Encoding.ASCII.GetBytes(value));
-        }
-
-        protected  int GetPropertyLength(string name, int valueLength)
-        {
-            return NameLengthSize + name.Length + ValueLengthSize + valueLength;
-        }
-
-        protected void AddBasicProperties(Span<byte> output)
-        {
-            //  Add socket type property
-            string socketName = GetSocketName(Options.SocketType);
-            int written = AddProperty(output, ZmtpPropertySocketType, socketName);
-            output = output.Slice(written);
-            
-            //  Add identity property
-            if (Options.SocketType == ZmqSocketType.Req || 
-                Options.SocketType == ZmqSocketType.Dealer || 
-                Options.SocketType == ZmqSocketType.Router)
-            {
-                if (Options.Identity != null)
-                {
-                    written = AddProperty(output, ZmtpPropertyIdentity, Options.Identity);
-                    output = output.Slice(written);
-                }
-                else
-                {
-                    written = AddProperty(output, ZmtpPropertyIdentity, new byte[0]);
-                    output = output.Slice(written);
-                }
-            }
-        }
-
-        protected int BasicPropertiesLength
-        {
-            get
-            {
-                string socketName = GetSocketName(Options.SocketType);
-
-                int length = GetPropertyLength(ZmtpPropertySocketType, socketName.Length);
-
-                if (Options.SocketType == ZmqSocketType.Req ||
-                    Options.SocketType == ZmqSocketType.Dealer ||
-                    Options.SocketType == ZmqSocketType.Router)
-                    length += GetPropertyLength(ZmtpPropertyIdentity, Options.IdentitySize);
-
-                return length;    
-            }
-        }
-
-        protected void MakeCommandWithBasicProperties(ref Msg msg, string prefix)
-        {
-            int commandSize = 1 + prefix.Length + BasicPropertiesLength;
-            msg.InitPool(commandSize);
-            msg.Put((byte)prefix.Length, 0);
-            msg.Put(Encoding.ASCII, prefix, 1);
-            
-            AddBasicProperties(msg.Slice(prefix.Length + 1));
-        }
-
-        /// <summary>
-        /// Parses a metadata.
-        /// Metadata consists of a list of properties consisting of
-        /// name and value as size-specified strings.
-        /// </summary>
-        /// <returns>Returns true on success and false on error.</returns>
-        protected bool ParseMetadata(Span<byte> source)
-        {
-            while (source.Length > 1)
-            {
-                int nameLength = source[0];
-                source = source.Slice(NameLengthSize);
-                if (source.Length < nameLength)
-                    break;
-
-                string name = SpanUtility.ToAscii(source.Slice(0, nameLength));
-                source = source.Slice(nameLength);
-                if (source.Length < ValueLengthSize)
-                    break;
-
-                int valueLength = NetworkOrderBitsConverter.ToInt32(source);
-                source = source.Slice(ValueLengthSize);
-                if (source.Length < valueLength)
-                    break;
-                
-                byte[] value = new byte[valueLength];
-                source.Slice(0, valueLength).CopyTo(value);
-                source = source.Slice(valueLength);
-
-                if (name == ZmtpPropertyIdentity && Options.RecvIdentity)
-                    PeerIdentity = value;
-                else if (name == ZmtpPropertySocketType) 
-                {
-                    if (!CheckSocketType(Encoding.ASCII.GetString(value)))
-                        return false;
-                } 
-                else
-                {
-                    if (!GetProperty(name, value, valueLength))
-                        return false;
-                }
-            }
-            
-            if (source.Length > 0)
-                return false;
-
-            return true;
-        }
-
-        /// <summary>
-        /// This is called by ParseProperty method whenever it
-        /// parses a new property. The function returns true
-        /// on success and false on error. Signaling error prevents parser from
-        /// parsing remaining data.
-        /// Derived classes are supposed to override this
-        /// method to handle custom processing. 
-        /// </summary>
-        /// <returns></returns>
-        protected virtual bool GetProperty(string name, byte[] output, int size)
-        {
-            //  Default implementation does not check
-            //  property values and returns true to signal success.
-            return true;
-        }
-
-        /// <summary>
-        /// Returns true iff socket associated with the mechanism
-        /// is compatible with a given socket type 'type'.
-        /// </summary>
-        /// <returns></returns>
-        private bool CheckSocketType(string type)
-        {
-            switch (Options.SocketType)
-            {
-                case ZmqSocketType.Pair:
-                    return type == SocketNames.Pair;
-                case ZmqSocketType.Pub:
-                case ZmqSocketType.Xpub:
-                    return type == SocketNames.Sub || type == SocketNames.Xsub;
-                case ZmqSocketType.Sub:
-                case ZmqSocketType.Xsub:
-                    return type == SocketNames.Pub || type == SocketNames.Xpub;
-                case ZmqSocketType.Req:
-                    return type == SocketNames.Rep || type == SocketNames.Router;
-                case ZmqSocketType.Rep:
-                    return type == SocketNames.Req || type == SocketNames.Dealer;
-                case ZmqSocketType.Dealer:
-                    return type == SocketNames.Dealer || type == SocketNames.Router || type == SocketNames.Rep;
-                case ZmqSocketType.Router:
-                    return type == SocketNames.Dealer || type == SocketNames.Router || type == SocketNames.Req;
-                case ZmqSocketType.Pull:
-                    return type == SocketNames.Push;
-                case ZmqSocketType.Push:
-                    return type == SocketNames.Pull;
-                case ZmqSocketType.Server:
-                    return type == SocketNames.Client;
-                case ZmqSocketType.Client:
-                    return type == SocketNames.Server;
-                case ZmqSocketType.Peer:
-                    return type == SocketNames.Peer;
-                case ZmqSocketType.Radio:
-                    return type == SocketNames.Dish;
-                case ZmqSocketType.Dish:
-                    return type == SocketNames.Radio;
-                case ZmqSocketType.Gather:
-                    return type == SocketNames.Scatter;
-                case ZmqSocketType.Scatter:
-                    return type == SocketNames.Gather;
-                default:
-                    return false;
-            }
-        }
-
-        protected bool CheckBasicCommandStructure(ref Msg msg)
-        {
-            if (msg.Size <= 1 || 
-                msg.Size <= msg[0]) {
-                // TODO: Session.Socket.EventHandshakeFailedProtocol 
-
-                return false;
-            }
-            return true;
-        }
-        
-        internal protected bool IsCommand(string command, ref Msg msg)
-        {
-            if (msg.Size >= command.Length + 1 && msg[0] == command.Length)
-            {
-                return msg.GetString(Encoding.ASCII, 1, msg[0]) == command;
-            }
-            return false;
-        }
-    }
-}

+ 0 - 98
Communication/NetMQ/Core/Mechanisms/NullMechanism.cs

@@ -1,98 +0,0 @@
-using System;
-using System.Text;
-using NetMQ.Core.Utils;
-
-namespace NetMQ.Core.Mechanisms
-{
-    internal class NullMechanism : Mechanism
-    {
-        const string ReadyCommandName = "READY";
-        private const string ErrorCommandName = "ERROR";
-        private const int ErrorReasonLengthSize = 1;
-
-        bool m_readyCommandSent;
-        bool m_readyCommandReceived;
-        bool m_errorCommandReceived;
-
-        public NullMechanism(SessionBase session, Options options) : base(session, options)
-        {
-        }
-
-        public override void Dispose()
-        {
-        }
-
-        public override MechanismStatus Status
-        {
-            get
-            {
-                if (m_readyCommandSent && m_readyCommandReceived)
-                    return MechanismStatus.Ready;
-
-                bool commandSent = m_readyCommandSent;
-                bool commandReceived = m_readyCommandReceived || m_errorCommandReceived;
-                return commandSent && commandReceived ? MechanismStatus.Error : MechanismStatus.Handshaking;
-            }
-        }
-
-        PushMsgResult ProcessReadyCommand(Span<byte> commandData)
-        {
-            m_readyCommandReceived = true;
-            if (!ParseMetadata(commandData.Slice(ReadyCommandName.Length + 1)))
-                return PushMsgResult.Error;
-
-            return PushMsgResult.Ok;
-        }
-
-        PushMsgResult ProcessErrorCommand(Span<byte> commandData)
-        {
-            int fixedPrefixSize = ErrorCommandName.Length + 1 + ErrorReasonLengthSize;
-            if (commandData.Length < fixedPrefixSize)
-                return PushMsgResult.Error;
-
-            int errorReasonLength = commandData[ErrorCommandName.Length + 1];
-            if (errorReasonLength > commandData.Length - fixedPrefixSize)
-                return PushMsgResult.Error;
-
-            string errorReason = SpanUtility.ToAscii(commandData.Slice(fixedPrefixSize, errorReasonLength));
-
-            // TODO: handle error, nothing todo at the moment as monitoring and zap are not yet implemented
-
-            m_errorCommandReceived = true;
-            return PushMsgResult.Ok;
-        }
-
-        public override PullMsgResult NextHandshakeCommand(ref Msg msg)
-        {
-            if (m_readyCommandSent)
-                return PullMsgResult.Empty;
-
-            MakeCommandWithBasicProperties(ref msg, ReadyCommandName);
-            m_readyCommandSent = true;
-
-            return PullMsgResult.Ok;
-        }
-
-        public override PushMsgResult ProcessHandshakeCommand(ref Msg msg)
-        {
-            if (m_readyCommandReceived || m_errorCommandReceived)
-                return PushMsgResult.Error;
-
-            PushMsgResult result;
-            if (IsCommand(ReadyCommandName, ref msg))
-                result = ProcessReadyCommand(msg);
-            else if (IsCommand(ErrorCommandName, ref msg))
-                result = ProcessErrorCommand(msg);
-            else
-                return PushMsgResult.Error;
-
-            if (result == PushMsgResult.Ok)
-            {
-                msg.Close();
-                msg.InitEmpty();
-            }
-
-            return result;
-        }
-    }
-}

Some files were not shown because too many files changed in this diff