diff --git a/Datasync.Toolkit.sln b/Datasync.Toolkit.sln
index 1dc0da02..f943bc3a 100644
--- a/Datasync.Toolkit.sln
+++ b/Datasync.Toolkit.sln
@@ -11,7 +11,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D59F1489-5D74-4F52-B78B-88037EAB2838}"
ProjectSection(SolutionItems) = preProject
tests\Directory.Build.props = tests\Directory.Build.props
- tests\EFCore.Packages.props = tests\EFCore.Packages.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Datasync.Server.Abstractions", "src\CommunityToolkit.Datasync.Server.Abstractions\CommunityToolkit.Datasync.Server.Abstractions.csproj", "{852F8266-603E-4FC6-A5CB-E492E747924F}"
@@ -44,6 +43,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Datasync.T
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{2D2A6EFC-015D-4258-96D4-24C78F8C59F9}"
ProjectSection(SolutionItems) = preProject
+ Directory.Packages.props = Directory.Packages.props
.github\workflows\SignedPackageFileList.txt = .github\workflows\SignedPackageFileList.txt
.github\workflows\SignedTemplateFileList.txt = .github\workflows\SignedTemplateFileList.txt
EndProjectSection
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0f2295f1..e37b40b0 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -3,34 +3,37 @@
truetrue
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
+
diff --git a/src/CommunityToolkit.Datasync.Client/CommunityToolkit.Datasync.Client.csproj b/src/CommunityToolkit.Datasync.Client/CommunityToolkit.Datasync.Client.csproj
index 9c75786f..f4831587 100644
--- a/src/CommunityToolkit.Datasync.Client/CommunityToolkit.Datasync.Client.csproj
+++ b/src/CommunityToolkit.Datasync.Client/CommunityToolkit.Datasync.Client.csproj
@@ -1,4 +1,4 @@
-
+The client capabilities for developing applications using the Datasync Toolkit.
@@ -12,7 +12,7 @@
-
+
diff --git a/src/CommunityToolkit.Datasync.Client/Paging/ConcurrentObservableCollection.cs b/src/CommunityToolkit.Datasync.Client/Paging/ConcurrentObservableCollection.cs
index 371fdc3e..05f53379 100644
--- a/src/CommunityToolkit.Datasync.Client/Paging/ConcurrentObservableCollection.cs
+++ b/src/CommunityToolkit.Datasync.Client/Paging/ConcurrentObservableCollection.cs
@@ -16,7 +16,7 @@ namespace CommunityToolkit.Datasync.Client;
///
public class ConcurrentObservableCollection : ObservableCollection
{
- private readonly SynchronizationContext context = SynchronizationContext.Current!;
+ private readonly SynchronizationContext? currentContext = SynchronizationContext.Current;
private bool suppressNotification = false;
///
@@ -151,31 +151,30 @@ public bool ReplaceIf(Func match, T replacement)
///
/// The event arguments
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
- => DispatchCallback(new SynchronizationContextAdapter(this.context), RaiseCollectionChanged, e);
+ {
+ if (this.currentContext is null || SynchronizationContext.Current == this.currentContext)
+ {
+ RaiseCollectionChanged(e);
+ }
+ else
+ {
+ this.currentContext.Send(RaiseCollectionChanged, e);
+ }
+ }
///
/// Event trigger to indicate that a property has changed in a thread-safe way.
///
/// The event arguments
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
- => DispatchCallback(new SynchronizationContextAdapter(this.context), RaisePropertyChanged, e);
-
- ///
- /// Dispatches the callback to the synchronization context. If the synchronization context is
- /// the current one, we can avoid a dispatch and just call the callback directly.
- ///
- /// The context to send the request to.
- /// The callback method.
- /// The parameter for the callback method.
- internal static void DispatchCallback(ISynchronizationContext context, SendOrPostCallback callback, object? param)
{
- if (context.IsCurrentContext())
+ if (this.currentContext is null || SynchronizationContext.Current == this.currentContext)
{
- callback(param);
+ RaisePropertyChanged(e);
}
else
{
- context.Send(callback, param);
+ this.currentContext.Send(RaisePropertyChanged, e);
}
}
diff --git a/src/CommunityToolkit.Datasync.Client/Paging/SynchronizationContextAdapter.cs b/src/CommunityToolkit.Datasync.Client/Paging/SynchronizationContextAdapter.cs
deleted file mode 100644
index 7e855179..00000000
--- a/src/CommunityToolkit.Datasync.Client/Paging/SynchronizationContextAdapter.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics.CodeAnalysis;
-
-namespace CommunityToolkit.Datasync.Client.Paging;
-
-///
-/// An abstraction layer for the that we use
-/// for mocking out context calls.
-///
-internal interface ISynchronizationContext
-{
- bool IsCurrentContext();
- void Send(SendOrPostCallback callback, object? state);
-}
-
-///
-/// A concrete implementation of the that handles
-/// a real synchronization context.
-///
-[ExcludeFromCodeCoverage]
-internal class SynchronizationContextAdapter(SynchronizationContext context) : ISynchronizationContext
-{
- public bool IsCurrentContext()
- => SynchronizationContext.Current == context;
-
- public void Send(SendOrPostCallback callback, object? state)
- => context.Send(callback, state);
-}
diff --git a/src/CommunityToolkit.Datasync.Client/Serialization/DatasyncSerializer.cs b/src/CommunityToolkit.Datasync.Client/Serialization/DatasyncSerializer.cs
index a50a206e..a2622238 100644
--- a/src/CommunityToolkit.Datasync.Client/Serialization/DatasyncSerializer.cs
+++ b/src/CommunityToolkit.Datasync.Client/Serialization/DatasyncSerializer.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Azure.Core.Serialization;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -58,7 +57,7 @@ public static string Serialize(object obj, Type objType)
new DateTimeOffsetConverter(),
new DateTimeConverter(),
new TimeOnlyConverter(),
- new MicrosoftSpatialGeoJsonConverter()
+ new SpatialGeoJsonConverter()
},
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
diff --git a/src/CommunityToolkit.Datasync.Client/Serialization/JsonExtensions.cs b/src/CommunityToolkit.Datasync.Client/Serialization/JsonExtensions.cs
new file mode 100644
index 00000000..fab10d3c
--- /dev/null
+++ b/src/CommunityToolkit.Datasync.Client/Serialization/JsonExtensions.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Text.Json;
+
+namespace CommunityToolkit.Datasync.Client.Serialization;
+
+///
+/// Extension methods for System.Text.Json.
+///
+internal static class JsonExtensions
+{
+ ///
+ /// Asserts that the current token of the matches the .
+ ///
+ /// The to assert.
+ /// The expected of the current token.
+ /// The current token did not match the .
+ public static void Expect(in this Utf8JsonReader reader, JsonTokenType expectedTokenType)
+ {
+ if (reader.TokenType != expectedTokenType)
+ {
+ throw new JsonException($"Deserialization failed. Expected token: '{expectedTokenType}'.");
+ }
+ }
+}
diff --git a/src/CommunityToolkit.Datasync.Client/Serialization/SpatialGeoJsonConverter.cs b/src/CommunityToolkit.Datasync.Client/Serialization/SpatialGeoJsonConverter.cs
new file mode 100644
index 00000000..33e62fea
--- /dev/null
+++ b/src/CommunityToolkit.Datasync.Client/Serialization/SpatialGeoJsonConverter.cs
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Spatial;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace CommunityToolkit.Datasync.Client.Serialization;
+
+///
+/// Converters between Microsoft.Spatial types and GeoJSON
+///
+///
+/// Only handles GeographyPoint at this time.
+///
+///
+public class SpatialGeoJsonConverter : JsonConverter