Skip to content

Commit

Permalink
resolved additional comments
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreasJakof-BASF committed Oct 15, 2024
1 parent 57d24a0 commit a7f3dbe
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,104 +2,74 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.\
// ------------------------------------------------------------------------------

#if NET5_0_OR_GREATER

using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System;
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;

using System.Collections.Generic;
using System.Linq;

#if NET5_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif

namespace Microsoft.Kiota.Abstractions.Serialization;
public static partial class KiotaJsonSerializer
{
#if NET8_0_OR_GREATER
#else
/// <summary>
/// Palceholder for .NET &lt; 8
/// </summary>
private class RequiresDynamicCodeAttribute : Attribute
{
public RequiresDynamicCodeAttribute(string _) { }
}

#endif
private static bool IsIParsable(this Type type) => type.IsAssignableTo(typeof(IParsable));

private static class KiotaJsonDeserializationWrapperFactory
{
private static readonly ConcurrentDictionary<Type, IKiotaJsonDeserializationWrapper> _deserializers = new ConcurrentDictionary<Type, IKiotaJsonDeserializationWrapper>();

[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
public static IKiotaJsonDeserializationWrapper Create(Type type) => type.IsIParsable() ? _deserializers.GetOrAdd(type, CreateInternal) : throw new ArgumentException("The given Type is not of IParsable", nameof(type));

[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
private static IKiotaJsonDeserializationWrapper CreateInternal([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type targetType)
{
if(Activator.CreateInstance(typeof(KiotaJsonDeserializationWrapper<>).MakeGenericType(targetType)) is IKiotaJsonDeserializationWrapper deserializer)
return deserializer;
else
throw new InvalidOperationException($"Unable to create deserializer for type {targetType}");
}
}

private interface IKiotaJsonDeserializationWrapper
{
Task<IParsable?> DeserializeAsync(Stream stream, CancellationToken cancellationToken = default);
Task<IParsable?> DeserializeAsync(string serializedRepresentation, CancellationToken cancellationToken = default);
Task<IEnumerable<IParsable>> DeserializeCollectionAsync(Stream stream, CancellationToken cancellationToken = default);
Task<IEnumerable<IParsable>> DeserializeCollectionAsync(string serializedRepresentation, CancellationToken cancellationToken = default);
}

private class KiotaJsonDeserializationWrapper<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> : IKiotaJsonDeserializationWrapper where T : IParsable
{
public async Task<IParsable?> DeserializeAsync(Stream stream, CancellationToken cancellationToken = default) => await KiotaJsonSerializer.DeserializeAsync<T>(stream, cancellationToken);
public async Task<IParsable?> DeserializeAsync(string serializedRepresentation, CancellationToken cancellationToken = default) => await KiotaJsonSerializer.DeserializeAsync<T>(serializedRepresentation, cancellationToken);
public async Task<IEnumerable<IParsable>> DeserializeCollectionAsync(Stream stream, CancellationToken cancellationToken = default) => (await KiotaJsonSerializer.DeserializeCollectionAsync<T>(stream, cancellationToken)).OfType<IParsable>();
public async Task<IEnumerable<IParsable>> DeserializeCollectionAsync(string serializedRepresentation, CancellationToken cancellationToken = default) => (await KiotaJsonSerializer.DeserializeCollectionAsync<T>(serializedRepresentation, cancellationToken)).OfType<IParsable>();
}

/// <summary>
/// Deserializes the given string into an object.
/// </summary>
/// <param name="targetType">The target type to deserialize</param>
/// <param name="serializedRepresentation">The serialized representation of the object.</param>
/// <param name="cancellationToken">The cancellation token for the task</param>
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
#if NET5_0_OR_GREATER
public static Task<IParsable?> DeserializeAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type targetType, string serializedRepresentation, CancellationToken cancellationToken = default)
=> KiotaJsonDeserializationWrapperFactory.Create(targetType).DeserializeAsync(serializedRepresentation, cancellationToken);
#else
public static Task<IParsable?> DeserializeAsync(Type targetType, string serializedRepresentation , CancellationToken cancellationToken = default)
#endif
=> KiotaSerializer.KiotaDeserializationWrapperFactory.Create(targetType).DeserializeAsync(_jsonContentType, serializedRepresentation, cancellationToken);

/// <summary>
/// Deserializes the given stream into an object.
/// </summary>
/// <param name="targetType">The target type to deserialize</param>
/// <param name="stream">The stream to deserialize.</param>
/// <param name="cancellationToken">The cancellation token for the task</param>
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
#if NET5_0_OR_GREATER
public static Task<IParsable?> DeserializeAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type targetType, Stream stream, CancellationToken cancellationToken = default)
=> KiotaJsonDeserializationWrapperFactory.Create(targetType).DeserializeAsync(stream, cancellationToken);
#else
public static Task<IParsable?> DeserializeAsync(Type targetType, Stream stream, CancellationToken cancellationToken = default)
#endif
=> KiotaSerializer.KiotaDeserializationWrapperFactory.Create(targetType).DeserializeAsync(_jsonContentType, stream, cancellationToken);

/// <summary>
/// Deserializes the given stream into a collection of objects based on the content type.
/// </summary>
/// <param name="targetType">The target type to deserialize</param>
/// <param name="stream">The stream to deserialize.</param>
/// <param name="cancellationToken">The cancellation token for the task</param>
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
public static Task<IEnumerable<IParsable>> DeserializeCollectionAsync(Type targetType, Stream stream, CancellationToken cancellationToken = default)
=> KiotaJsonDeserializationWrapperFactory.Create(targetType).DeserializeCollectionAsync(stream, cancellationToken);
=> KiotaSerializer.KiotaDeserializationWrapperFactory.Create(targetType).DeserializeCollectionAsync(_jsonContentType, stream, cancellationToken);

/// <summary>
/// Deserializes the given stream into a collection of objects based on the content type.
/// </summary>
/// <param name="targetType">The target type to deserialize</param>
/// <param name="serializedRepresentation">The serialized representation of the object.</param>
/// <param name="cancellationToken">The cancellation token for the task</param>
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
public static Task<IEnumerable<IParsable>> DeserializeCollectionAsync(Type targetType, string serializedRepresentation, CancellationToken cancellationToken = default)
=> KiotaJsonDeserializationWrapperFactory.Create(targetType).DeserializeCollectionAsync(serializedRepresentation, cancellationToken);
=> KiotaSerializer.KiotaDeserializationWrapperFactory.Create(targetType).DeserializeCollectionAsync(_jsonContentType, serializedRepresentation, cancellationToken);
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,46 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
// ------------------------------------------------------------------------------

#if NET5_0_OR_GREATER


using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System;
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;



#if NET5_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif

namespace Microsoft.Kiota.Abstractions.Serialization;

public static partial class KiotaSerializer
{
#if NET8_0_OR_GREATER
#else
/// <summary>
/// Palceholder for .NET &lt; 8
/// </summary>
private class RequiresDynamicCodeAttribute : Attribute
{
public RequiresDynamicCodeAttribute(string _) { }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsIParsable(this Type type) => typeof(IParsable).IsAssignableFrom(type);

#endif
private static bool IsIParsable(this Type type) => type.IsAssignableTo(typeof(IParsable));

private static class KiotaDeserializationWrapperFactory
internal static class KiotaDeserializationWrapperFactory
{
private static readonly ConcurrentDictionary<Type, IKiotaDeserializationWrapper> _deserializers = new ConcurrentDictionary<Type, IKiotaDeserializationWrapper>();

#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
public static IKiotaDeserializationWrapper Create(Type type) => type.IsIParsable() ? _deserializers.GetOrAdd(type, CreateInternal) : throw new ArgumentException("The given Type is not of IParsable", nameof(type));

#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
#if NET5_0_OR_GREATER
private static IKiotaDeserializationWrapper CreateInternal([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type targetType)
#else
private static IKiotaDeserializationWrapper CreateInternal(Type targetType)
#endif
{
if(Activator.CreateInstance(typeof(KiotaDeserializationWrapper<>).MakeGenericType(targetType)) is IKiotaDeserializationWrapper deserializer)
return deserializer;
Expand All @@ -47,16 +50,19 @@ private static IKiotaDeserializationWrapper CreateInternal([DynamicallyAccessedM
}
}

private interface IKiotaDeserializationWrapper
internal interface IKiotaDeserializationWrapper
{
Task<IParsable?> DeserializeAsync(string contentType, Stream stream, CancellationToken cancellationToken = default);
Task<IParsable?> DeserializeAsync(string contentType, string serializedRepresentation, CancellationToken cancellationToken = default);
Task<IEnumerable<IParsable>> DeserializeCollectionAsync(string contentType, Stream stream, CancellationToken cancellationToken = default);
Task<IEnumerable<IParsable>> DeserializeCollectionAsync(string contentType, string serializedRepresentation, CancellationToken cancellationToken = default);
}

private class KiotaDeserializationWrapper<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> : IKiotaDeserializationWrapper where T : IParsable
{
#if NET5_0_OR_GREATER
internal class KiotaDeserializationWrapper<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> : IKiotaDeserializationWrapper where T : IParsable
#else
internal class KiotaDeserializationWrapper<T> : IKiotaDeserializationWrapper where T : IParsable
#endif
{
public async Task<IParsable?> DeserializeAsync(string contentType, Stream stream, CancellationToken cancellationToken = default) => await KiotaSerializer.DeserializeAsync<T>(contentType, stream, cancellationToken);
public async Task<IParsable?> DeserializeAsync(string contentType, string serializedRepresentation, CancellationToken cancellationToken = default) => await KiotaSerializer.DeserializeAsync<T>(contentType, serializedRepresentation, cancellationToken);
public async Task<IEnumerable<IParsable>> DeserializeCollectionAsync(string contentType, Stream stream, CancellationToken cancellationToken = default) => (await KiotaSerializer.DeserializeCollectionAsync<T>(contentType, stream, cancellationToken)).OfType<IParsable>();
Expand All @@ -72,8 +78,14 @@ private class KiotaDeserializationWrapper<[DynamicallyAccessedMembers(Dynamicall
/// <param name="cancellationToken">The cancellation token for the task</param>
/// <returns></returns>

[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
#if NET5_0_OR_GREATER
public static Task<IParsable?> DeserializeAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type, string contentType, string serializedRepresentation, CancellationToken cancellationToken = default)
#else
public static Task<IParsable?> DeserializeAsync(Type type, string contentType, string serializedRepresentation, CancellationToken cancellationToken = default)
#endif
=> KiotaDeserializationWrapperFactory.Create(type).DeserializeAsync(contentType, serializedRepresentation, cancellationToken);

/// <summary>
Expand All @@ -84,8 +96,14 @@ private class KiotaDeserializationWrapper<[DynamicallyAccessedMembers(Dynamicall
/// <param name="stream">The stream to deserialize.</param>
/// <param name="cancellationToken">The cancellation token for the task</param>
/// <returns></returns>
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
#if NET5_0_OR_GREATER
public static Task<IParsable?> DeserializeAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type, string contentType, Stream stream, CancellationToken cancellationToken = default)
#else
public static Task<IParsable?> DeserializeAsync(Type type, string contentType, Stream stream, CancellationToken cancellationToken = default)
#endif
=> KiotaDeserializationWrapperFactory.Create(type).DeserializeAsync(contentType, stream, cancellationToken);

/// <summary>
Expand All @@ -95,8 +113,9 @@ private class KiotaDeserializationWrapper<[DynamicallyAccessedMembers(Dynamicall
/// <param name="contentType">The content type of the stream.</param>
/// <param name="stream">The stream to deserialize.</param>
/// <param name="cancellationToken">The cancellation token for the task</param>

[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
public static Task<IEnumerable<IParsable>> DeserializeCollectionAsync(Type type, string contentType, Stream stream, CancellationToken cancellationToken = default)
=> KiotaDeserializationWrapperFactory.Create(type).DeserializeCollectionAsync(contentType, stream, cancellationToken);

Expand All @@ -107,8 +126,9 @@ public static Task<IEnumerable<IParsable>> DeserializeCollectionAsync(Type type,
/// <param name="contentType">The content type of the stream.</param>
/// <param name="serializedRepresentation">The serialized representation of the object.</param>
/// <param name="cancellationToken">The cancellation token for the task</param>
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#if NET7_0_OR_GREATER
[RequiresDynamicCode("Activator creates an instance of a generic class with the Target Type as the generic type argument.")]
#endif
public static Task<IEnumerable<IParsable>> DeserializeCollectionAsync(Type type, string contentType, string serializedRepresentation, CancellationToken cancellationToken = default)
=> KiotaDeserializationWrapperFactory.Create(type).DeserializeCollectionAsync(contentType, serializedRepresentation, cancellationToken);
}
#endif
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#if NET5_0_OR_GREATER

using Microsoft.Kiota.Abstractions.Serialization;
using Microsoft.Kiota.Abstractions.Tests.Mocks;
using Moq;
Expand Down Expand Up @@ -74,4 +74,3 @@ public async Task DeserializesCollectionOfObjectUntypedAsync()
Assert.Equal("123", first.Id);
}
}
#endif

0 comments on commit a7f3dbe

Please sign in to comment.