Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Native AOT #1348

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json;

namespace JustSaying.Sample.Restaurant.OrderingApi;

public class MessagingJsonSerializerOptions
{
public JsonSerializerOptions SerializerOptions { get; } = new();
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Text.Json;
using JustSaying.Messaging;
using JustSaying.Messaging.MessageSerialization;
using JustSaying.Sample.Restaurant.Models;
Expand Down Expand Up @@ -31,11 +30,15 @@
cfg.SerializerOptions.TypeInfoResolverChain.Insert(0, ApplicationJsonContext.Default);
});

builder.Services.Configure<JustSayingJsonSerializerOptions>(cfg =>
builder.Services.Configure<MessagingJsonSerializerOptions>(cfg =>
{
cfg.SerializerOptions.TypeInfoResolverChain.Insert(0, ApplicationJsonContext.Default);
});

builder.Services.AddSingleton<IMessageSerializationFactory>(sp =>
new SystemTextJsonSerializationFactory(sp.GetRequiredService<IOptions<MessagingJsonSerializerOptions>>().Value.SerializerOptions));

#pragma warning disable IL2026 // We provide SystemTextJsonSerializationFactory, which is AOT safe
builder.Services.AddJustSaying(config =>
{
config.Client(x =>
Expand Down Expand Up @@ -78,6 +81,7 @@
x.WithTopic<OrderOnItsWayEvent>();
});
});
#pragma warning restore IL2026

// Added a message handler for message type for 'OrderReadyEvent' on topic 'orderreadyevent' and queue 'orderreadyevent'
builder.Services.AddJustSayingHandler<OrderReadyEvent, OrderReadyEventHandler>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace Microsoft.Extensions.DependencyInjection;
[EditorBrowsable(EditorBrowsableState.Never)]
public static class IServiceCollectionExtensions
{
private const string AttributeRequiresUnreferencedCodeMessage = "The AWSSDK.Extensions.NETCore.Setup package has not been updated to support Native AOT compilations";

/// <summary>
/// Adds JustSaying services to the service collection using AWS configuration.
/// </summary>
Expand All @@ -27,6 +29,9 @@ public static class IServiceCollectionExtensions
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/>, <paramref name="configuration"/> or <paramref name="builderConfig"/> is <see langword="null"/>.
/// </exception>
#if NET8_0_OR_GREATER
[RequiresUnreferencedCode(AttributeRequiresUnreferencedCodeMessage)]
#endif
public static void AddJustSayingWithAwsConfig(this IServiceCollection services, IConfiguration configuration, Action<MessagingBusBuilder> builderConfig)
{
if (services is null)
Expand Down Expand Up @@ -59,6 +64,9 @@ public static void AddJustSayingWithAwsConfig(this IServiceCollection services,
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/>, <paramref name="configuration"/> or <paramref name="builderConfig"/> is <see langword="null"/>.
/// </exception>
#if NET8_0_OR_GREATER
[RequiresUnreferencedCode(AttributeRequiresUnreferencedCodeMessage)]
#endif
public static void AddJustSayingWithAwsConfig(this IServiceCollection services, IConfiguration configuration, Action<MessagingBusBuilder, IServiceProvider> builderConfig)
{
if (services is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@
using JustSaying.Models;
using JustSaying.Naming;
using Microsoft.Extensions.DependencyInjection.Extensions;
#if NET8_0_OR_GREATER
using System.Text.Json;
using Microsoft.Extensions.Options;
using System.Diagnostics.CodeAnalysis;
#endif

namespace Microsoft.Extensions.DependencyInjection;

Expand All @@ -26,6 +21,8 @@
[EditorBrowsable(EditorBrowsableState.Never)]
public static class IServiceCollectionExtensions
{
private const string UnreferencedCodeMessage = "The default IMessageSerializationFactory implementation requires unreferenced code.";

/// <summary>
/// Adds JustSaying services to the service collection.
/// </summary>
Expand All @@ -36,6 +33,9 @@
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> is <see langword="null"/>.
/// </exception>
#if NET8_0_OR_GREATER
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
#endif
public static IServiceCollection AddJustSaying(this IServiceCollection services)
{
if (services == null)
Expand All @@ -57,6 +57,9 @@
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> or <paramref name="region"/> is <see langword="null"/>.
/// </exception>
#if NET8_0_OR_GREATER
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
#endif
public static IServiceCollection AddJustSaying(this IServiceCollection services, string region)
{
if (services == null)
Expand All @@ -66,7 +69,7 @@

if (string.IsNullOrWhiteSpace(region))
{
throw new ArgumentException("region must not be null or empty", nameof(region));

Check warning on line 72 in src/JustSaying.Extensions.DependencyInjection.Microsoft/IServiceCollectionExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/JustSaying.Extensions.DependencyInjection.Microsoft/IServiceCollectionExtensions.cs#L72

Added line #L72 was not covered by tests
}

return services.AddJustSaying(
Expand All @@ -85,6 +88,9 @@
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> or <paramref name="configure"/> is <see langword="null"/>.
/// </exception>
#if NET8_0_OR_GREATER
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
#endif
public static IServiceCollection AddJustSaying(this IServiceCollection services, Action<MessagingBusBuilder> configure)
{
if (services == null)
Expand All @@ -111,6 +117,9 @@
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> or <paramref name="configure"/> is <see langword="null"/>.
/// </exception>
#if NET8_0_OR_GREATER
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
#endif
public static IServiceCollection AddJustSaying(this IServiceCollection services, Action<MessagingBusBuilder, IServiceProvider> configure)
{
if (services == null)
Expand Down Expand Up @@ -140,11 +149,8 @@
services.TryAddSingleton<IMessageContextAccessor>(serviceProvider => serviceProvider.GetRequiredService<MessageContextAccessor>());
services.TryAddSingleton<IMessageContextReader>(serviceProvider => serviceProvider.GetRequiredService<MessageContextAccessor>());

#if NET8_0_OR_GREATER
services.TryAddSingleton<IMessageSerializationFactory>(sp => new TypedSystemTextJsonSerializationFactory(sp.GetRequiredService<IOptions<JustSayingJsonSerializerOptions>>().Value));
#else
services.TryAddSingleton<IMessageSerializationFactory, NewtonsoftSerializationFactory>();
#endif

services.TryAddSingleton<IMessageSubjectProvider, GenericMessageSubjectProvider>();
services.TryAddSingleton<IVerifyAmazonQueues, AmazonQueueCreator>();
services.TryAddSingleton<IMessageSerializationRegister>(
Expand Down
4 changes: 2 additions & 2 deletions src/JustSaying/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

internal static class Constants
{
internal const string SerializationUnreferencedCodeMessage = "JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.";
internal const string SerializationDynamicCodeMessage = "JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext.";
internal const string SerializationUnreferencedCodeMessage = "JSON serialization and deserialization might require types that cannot be statically analyzed. Use the generic SystemTextJsonSerializer<T>.";
internal const string SerializationDynamicCodeMessage = "JSON serialization and deserialization might require types that cannot be statically analyzed. Use the generic SystemTextJsonSerializer<T>.";
}
25 changes: 25 additions & 0 deletions src/JustSaying/Extensions/JsonElementExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#nullable enable
using System.Text.Json;

namespace JustSaying.Extensions;

internal static class JsonElementExtensions
{
#if NET8_0_OR_GREATER
public static bool TryGetStringProperty(this JsonElement element, string key, [NotNullWhen(true)] out string? value)
#else
public static bool TryGetStringProperty(this JsonElement element, string key, out string? value)
#endif
{
value = null;

Check warning on line 14 in src/JustSaying/Extensions/JsonElementExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/JustSaying/Extensions/JsonElementExtensions.cs#L14

Added line #L14 was not covered by tests
if (element.TryGetProperty(key, out var property)
&& property.ValueKind is JsonValueKind.String or JsonValueKind.Null
&& property.GetString() is {} propertyValue)

Check warning on line 17 in src/JustSaying/Extensions/JsonElementExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/JustSaying/Extensions/JsonElementExtensions.cs#L16-L17

Added lines #L16 - L17 were not covered by tests
{
value = propertyValue;
return true;

Check warning on line 20 in src/JustSaying/Extensions/JsonElementExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/JustSaying/Extensions/JsonElementExtensions.cs#L19-L20

Added lines #L19 - L20 were not covered by tests
}

return false;

Check warning on line 23 in src/JustSaying/Extensions/JsonElementExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/JustSaying/Extensions/JsonElementExtensions.cs#L23

Added line #L23 was not covered by tests
}
}
13 changes: 2 additions & 11 deletions src/JustSaying/Extensions/JsonSerializerOptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,9 @@
{
public static JsonTypeInfo<T> GetTypeInfo<T>(this JsonSerializerOptions options)
{
foreach (var info in options.TypeInfoResolverChain)
{
Console.WriteLine(info);
}

// This is not guarded as we want to throw if the desired type has not been configured for
martincostello marked this conversation as resolved.
Show resolved Hide resolved
var typeInfo = options.GetTypeInfo(typeof(T));
if (typeInfo is not JsonTypeInfo<T> genericTypeInfo)
{
throw new JsonException($"Could not find type info for the specified type {typeof(T).Name}");
}

return genericTypeInfo;
return (JsonTypeInfo<T>)typeInfo;

Check warning on line 14 in src/JustSaying/Extensions/JsonSerializerOptionsExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/JustSaying/Extensions/JsonSerializerOptionsExtensions.cs#L13-L14

Added lines #L13 - L14 were not covered by tests
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@
#if NET8_0_OR_GREATER
if (RuntimeFeature.IsDynamicCodeSupported)
{
#pragma warning disable IL2026
#pragma warning disable IL3050
#pragma warning disable IL2026
#pragma warning disable IL3050
return new NewtonsoftSerializationFactory();
#pragma warning restore
#pragma warning restore IL2026
#pragma warning disable IL3050
}
else
{
throw new NotSupportedException($"Newtonsoft.Json is not supported when compiled with the 'PublishTrimmed' option. Use {nameof(TypedSystemTextJsonSerializationFactory)} instead.");
throw new NotSupportedException($"Newtonsoft.Json is not supported when compiled with the 'PublishTrimmed' option. Use {nameof(SystemTextJsonSerializationFactory)} instead.");

Check warning on line 60 in src/JustSaying/Fluent/ServiceResolver/DefaultServiceResolver.cs

View check run for this annotation

Codecov / codecov/patch

src/JustSaying/Fluent/ServiceResolver/DefaultServiceResolver.cs#L60

Added line #L60 was not covered by tests
}
#else
return new NewtonsoftSerializationFactory();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public MessageFormatNotSupportedException(string message, Exception innerExcepti
}
#if !NET8_0_OR_GREATER

#if !NET8_0_OR_GREATER
protected MessageFormatNotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
using System.Text.Json;
using JustSaying.Models;
#if NET8_0_OR_GREATER
using System.Runtime.CompilerServices;
#endif

namespace JustSaying.Messaging.MessageSerialization;

#if NET8_0_OR_GREATER
[RequiresUnreferencedCode(Constants.SerializationUnreferencedCodeMessage)]
[RequiresDynamicCode(Constants.SerializationDynamicCodeMessage)]
#endif
public class SystemTextJsonSerializationFactory(JsonSerializerOptions options) : IMessageSerializationFactory
{
#pragma warning disable CS0618 // Keep using obsolete serializer for now until the next breaking version
#pragma warning disable IL2026 // Not used in contexts where dynamic code is not supported
#pragma warning disable IL3050
private readonly SystemTextJsonSerializer _serializer = new(options);
#pragma warning restore IL3050
#pragma warning restore IL2026
#pragma warning restore CS0618

public SystemTextJsonSerializationFactory()
: this(null)
{
}

public IMessageSerializer GetSerializer<T>() where T : Message => _serializer;
public IMessageSerializer GetSerializer<T>() where T : Message =>
#if !NET8_0_OR_GREATER
_serializer;
#else
RuntimeFeature.IsDynamicCodeSupported
? _serializer
: new SystemTextJsonSerializer<T>(options);
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ namespace JustSaying.Messaging.MessageSerialization;
[RequiresUnreferencedCode(Constants.SerializationUnreferencedCodeMessage)]
[RequiresDynamicCode(Constants.SerializationDynamicCodeMessage)]
#endif
public partial class SystemTextJsonSerializer : IMessageSerializer
[Obsolete("This API is deprecated, and will be removed in a later version. Use SystemTextJsonSerializer<T> instead.")]
hwoodiwiss marked this conversation as resolved.
Show resolved Hide resolved
public class SystemTextJsonSerializer : IMessageSerializer
{
private static readonly JsonSerializerOptions DefaultJsonSerializerOptions = new()
{
Expand Down
Loading
Loading