Skip to content

Commit

Permalink
Merge branch 'main' into feature/asyncdeserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
andrueastman authored May 6, 2024
2 parents 70fd568 + 0994df5 commit bc3f8e1
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/auto-merge-dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2.0.0
uses: dependabot/fetch-metadata@v2.1.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"

Expand Down
20 changes: 11 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,38 @@ Adds asynchronous deserialization support and marks synchronous as obsolete. htt
- Added IAsyncParseNodeFactory interface to provide asynchronous version of GetRootParseNode: GetRootParseNodeAsync.
- Added ParseNodeFactoryRegistry.GetRootParseNodeAsync method.
- Added ParseNodeProxyFactory.GetRootParseNodeAsync method
- Adds async overloads for serialization helpers

### Changed

- Marked synchronous deserialization methods as obsolete.
- Marked IParseNodeFactory.GetRootParseNode as obsolete.
- Refactored ParseNodeFactoryRegistry.GetFactory to support both asynchronous (IAsyncParseNodeFactory) and synchronous (IParseNodeFactory) factories.


## [1.8.4] - 2024-04-19

- Bumps Std.UriTemplate to version 0.0.57

## [1.8.3] - 2024-04-18

- Have set the license expression on the nuget package rather than bundling in a file (https://github.com/microsoft/kiota-abstractions-dotnet/issues/219)
- Have set the license expression on the nuget package rather than bundling in a file (<https://github.com/microsoft/kiota-abstractions-dotnet/issues/219>)

## [1.8.2] - 2024-04-18

- Have made System.Diagnostics.DiagnosticSource only be included on Net Standard's TFM & net 5 (https://github.com/microsoft/kiota-abstractions-dotnet/issues/218)
- Have made System.Diagnostics.DiagnosticSource only be included on Net Standard's TFM & net 5 (<https://github.com/microsoft/kiota-abstractions-dotnet/issues/218>)

## [1.8.1] - 2024-03-26

### Changed

- `MultipartBody` now supports an optional `fileName` parameter to specify the file name of the part. (https://github.com/microsoft/kiota-abstractions-dotnet/issues/212)
- `MultipartBody` now supports an optional `fileName` parameter to specify the file name of the part. (<https://github.com/microsoft/kiota-abstractions-dotnet/issues/212>)

## [1.8.0] - 2024-03-18

### Added

- Added support for untyped nodes. (https://github.com/microsoft/kiota-abstractions-dotnet/issues/175)
- Added support for untyped nodes. (<https://github.com/microsoft/kiota-abstractions-dotnet/issues/175>)

## [1.7.12] - 2024-03-08

Expand All @@ -61,7 +63,7 @@ Adds asynchronous deserialization support and marks synchronous as obsolete. htt

- Updated IParseNode enum methods `DynamicallyAccessedMembersAttribute` to `PublicFields`.
- Fixed AOT compiler warnings from ILC.

## [1.7.10] - 2024-02-26

### Changed
Expand Down Expand Up @@ -91,20 +93,20 @@ Adds asynchronous deserialization support and marks synchronous as obsolete. htt

### Changed

- Improve AllowedHost validator to throw an error if `https://` or `http://` prefix is present in a allowed host value.(https://github.com/microsoft/kiota-abstractions-dotnet/issues/165)
- Improve AllowedHost validator to throw an error if `https://` or `http://` prefix is present in a allowed host value.(<https://github.com/microsoft/kiota-abstractions-dotnet/issues/165>)

## [1.7.5] - 2024-01-11

### Changed

- Fixes missing query parameters when the parameter values are empty strings.(https://github.com/microsoft/kiota-abstractions-dotnet/issues/172)
- Fixes missing query parameters when the parameter values are empty strings.(<https://github.com/microsoft/kiota-abstractions-dotnet/issues/172>)

## [1.7.4] - 2024-01-09

### Changed

- Fixed Method not found error due to conflicting dependencies by updating Std.UriTemplate dependency.
- Fixed unicode characters decoding in URI (https://github.com/std-uritemplate/std-uritemplate/issues/114).
- Fixed unicode characters decoding in URI (<https://github.com/std-uritemplate/std-uritemplate/issues/114>).

## [1.7.3] - 2023-11-30

Expand Down Expand Up @@ -183,7 +185,7 @@ Adds asynchronous deserialization support and marks synchronous as obsolete. htt

### Fixed

- Fixed a bug where excess duplicate subscriptions would be created on the same property in the backing store causing performance issues in some scenarios. Related to https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/1994
- Fixed a bug where excess duplicate subscriptions would be created on the same property in the backing store causing performance issues in some scenarios. Related to <https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/1994>

## [1.3.0] - 2023-08-01

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
environments https://github.com/microsoft/vstest/issues/2469-->
<PackageReference Include="Microsoft.TestPlatform.ObjectModel" Version="17.9.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.7.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.8">
<PackageReference Include="xunit" Version="2.8.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Kiota.Abstractions.Serialization;
using Microsoft.Kiota.Abstractions.Tests.Mocks;
using Moq;
Expand All @@ -25,15 +26,15 @@ public void DefensiveObjectCollection()
Assert.Throws<ArgumentNullException>(() => KiotaSerializer.SerializeAsStream(_jsonContentType, (IEnumerable<TestEntity>)null));
}
[Fact]
public void SerializesObject()
public async Task SerializesObject()
{
var mockSerializationWriter = new Mock<ISerializationWriter>();
mockSerializationWriter.Setup(x => x.GetSerializedContent()).Returns(new MemoryStream(UTF8Encoding.UTF8.GetBytes("{'id':'123'}")));
var mockSerializationWriterFactory = new Mock<ISerializationWriterFactory>();
mockSerializationWriterFactory.Setup(x => x.GetSerializationWriter(It.IsAny<string>())).Returns(mockSerializationWriter.Object);
SerializationWriterFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockSerializationWriterFactory.Object;

var result = KiotaSerializer.SerializeAsString(_jsonContentType, new TestEntity()
var result = await KiotaSerializer.SerializeAsStringAsync(_jsonContentType, new TestEntity()
{
Id = "123"
});
Expand All @@ -45,15 +46,15 @@ public void SerializesObject()
mockSerializationWriter.Verify(x => x.GetSerializedContent(), Times.Once);
}
[Fact]
public void SerializesObjectCollection()
public async Task SerializesObjectCollection()
{
var mockSerializationWriter = new Mock<ISerializationWriter>();
mockSerializationWriter.Setup(x => x.GetSerializedContent()).Returns(new MemoryStream(UTF8Encoding.UTF8.GetBytes("[{'id':'123'}]")));
var mockSerializationWriterFactory = new Mock<ISerializationWriterFactory>();
mockSerializationWriterFactory.Setup(x => x.GetSerializationWriter(It.IsAny<string>())).Returns(mockSerializationWriter.Object);
SerializationWriterFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockSerializationWriterFactory.Object;

var result = KiotaSerializer.SerializeAsString(_jsonContentType, new List<TestEntity> {
var result = await KiotaSerializer.SerializeAsStringAsync(_jsonContentType, new List<TestEntity> {
new()
{
Id = "123"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,32 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl
var colleagueSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.Colleagues[0].BackingStore);
Assert.Single(colleagueSubscriptions);// only one subscription to be invoked for the collection "colleagues"
}

[Fact]
public void TestsBackingStoreNestedInvocationCounts()
{
// Arrange dummy user with initialized backing store
var invocationCount = 0;
var testUser = new TestEntity();
testUser.BackingStore.Subscribe((_, _, _) => invocationCount++, "testId");
testUser.Id = "84c747c1-d2c0-410d-ba50-fc23e0b4abbe"; // invocation site 1
var colleagues = new List<TestEntity>();
for(int i = 0; i < 10; i++)
{
colleagues.Add(new TestEntity
{
Id = "2fe22fe5-1132-42cf-90f9-1dc17e325a74",
BusinessPhones = new List<string>
{
"+1 234 567 891"
}
});
}
testUser.Colleagues = colleagues; // invocation site 2
testUser.BackingStore.InitializationCompleted = true; // initialize

Assert.Equal(2,invocationCount);// only called twice
}

/// <summary>
/// Helper function to pull out the private `subscriptions` collection property from the InMemoryBackingStore class
Expand Down
24 changes: 24 additions & 0 deletions src/serialization/KiotaJsonSerializer.Serialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
// ------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
#if NET5_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
Expand All @@ -27,9 +30,20 @@ public static Stream SerializeAsStream<T>(T value) where T : IParsable
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a string.</returns>
[Obsolete("This method is obsolete, use the async method instead")]
public static string SerializeAsString<T>(T value) where T : IParsable
=> KiotaSerializer.SerializeAsString(_jsonContentType, value);

/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="value">The object to serialize.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The serialized representation as a string.</returns>
public static Task<string> SerializeAsStringAsync<T>(T value, CancellationToken cancellationToken = default) where T : IParsable
=> KiotaSerializer.SerializeAsStringAsync(_jsonContentType, value, cancellationToken);

/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
Expand All @@ -45,7 +59,17 @@ public static Stream SerializeAsStream<T>(IEnumerable<T> value) where T : IParsa
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a string.</returns>
[Obsolete("This method is obsolete, use the async method instead")]
public static string SerializeAsString<T>(IEnumerable<T> value) where T : IParsable
=> KiotaSerializer.SerializeAsString(_jsonContentType, value);
/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="value">The object to serialize.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The serialized representation as a string.</returns>
public static Task<string> SerializeAsStringAsync<T>(IEnumerable<T> value, CancellationToken cancellationToken = default) where T : IParsable
=> KiotaSerializer.SerializeAsStringAsync(_jsonContentType, value, cancellationToken);

}
40 changes: 40 additions & 0 deletions src/serialization/KiotaSerializer.Serialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
#if NET5_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
Expand Down Expand Up @@ -37,6 +39,7 @@ public static Stream SerializeAsStream<T>(string contentType, T value) where T :
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a string.</returns>
[Obsolete("This method is obsolete, use the async method instead")]
public static string SerializeAsString<T>(string contentType, T value) where T : IParsable
{
using var stream = SerializeAsStream(contentType, value);
Expand All @@ -48,6 +51,19 @@ public static string SerializeAsString<T>(string contentType, T value) where T :
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The serialized representation as a string.</returns>
public static Task<string> SerializeAsStringAsync<T>(string contentType, T value, CancellationToken cancellationToken = default) where T : IParsable
{
using var stream = SerializeAsStream(contentType, value);
return GetStringFromStreamAsync(stream, cancellationToken);
}
/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a stream.</returns>
public static Stream SerializeAsStream<T>(string contentType, IEnumerable<T> value) where T : IParsable
{
Expand All @@ -62,16 +78,40 @@ public static Stream SerializeAsStream<T>(string contentType, IEnumerable<T> val
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a string.</returns>
[Obsolete("This method is obsolete, use the async method instead")]
public static string SerializeAsString<T>(string contentType, IEnumerable<T> value) where T : IParsable
{
using var stream = SerializeAsStream(contentType, value);
return GetStringFromStream(stream);
}
/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The serialized representation as a string.</returns>
public static Task<string> SerializeAsStringAsync<T>(string contentType, IEnumerable<T> value, CancellationToken cancellationToken = default) where T : IParsable
{
using var stream = SerializeAsStream(contentType, value);
return GetStringFromStreamAsync(stream, cancellationToken);
}
[Obsolete("This method is obsolete, use the async method instead")]
private static string GetStringFromStream(Stream stream)
{
using var reader = new StreamReader(stream);
return reader.ReadToEndAsync().ConfigureAwait(false).GetAwaiter().GetResult(); // so the asp.net projects don't get an error
}
private static async Task<string> GetStringFromStreamAsync(Stream stream, CancellationToken cancellationToken)
{
using var reader = new StreamReader(stream);
#if NET7_0_OR_GREATER
return await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
#else
return await reader.ReadToEndAsync().ConfigureAwait(false);
#endif
}
private static ISerializationWriter GetSerializationWriter(string contentType, object value)
{
if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType));
Expand Down

0 comments on commit bc3f8e1

Please sign in to comment.