diff --git a/Directory.Packages.props b/Directory.Packages.props
index 1a86e041b..dea93aa97 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -57,6 +57,7 @@
+
diff --git a/Directory.Packages.support.props b/Directory.Packages.support.props
index 400df97b8..05bf4a470 100644
--- a/Directory.Packages.support.props
+++ b/Directory.Packages.support.props
@@ -2,10 +2,13 @@
+
+
+
diff --git a/sample/Sample.Core/DataConvention.cs b/sample/Sample.Core/DataConvention.cs
index 23a591fd4..fa80c1a93 100644
--- a/sample/Sample.Core/DataConvention.cs
+++ b/sample/Sample.Core/DataConvention.cs
@@ -10,6 +10,7 @@
using IConventionContext = Rocket.Surgery.Conventions.IConventionContext;
[assembly: Convention(typeof(DataConvention))]
+
namespace Sample.Core
{
class DataConvention : IServiceConvention
@@ -18,12 +19,18 @@ public void Register(IConventionContext context, IConfiguration configuration, I
{
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
- services.AddPooledDbContextFactory(x => x
- .EnableDetailedErrors()
- .EnableSensitiveDataLogging()
- .EnableServiceProviderCaching()
- .UseSqlite(connection)
- );
+ services
+#if NETSTANDARD
+ .AddDbContextPool(
+#else
+ .AddPooledDbContextFactory(
+#endif
+ x => x
+ .EnableDetailedErrors()
+ .EnableSensitiveDataLogging()
+ .EnableServiceProviderCaching()
+ .UseSqlite(connection)
+ );
}
}
}
\ No newline at end of file
diff --git a/sample/Sample.Core/Domain/RocketDbContext.cs b/sample/Sample.Core/Domain/RocketDbContext.cs
index c33778e62..661f690f7 100644
--- a/sample/Sample.Core/Domain/RocketDbContext.cs
+++ b/sample/Sample.Core/Domain/RocketDbContext.cs
@@ -7,7 +7,7 @@ namespace Sample.Core.Domain
{
public class RocketDbContext : LpContext
{
- public RocketDbContext(DbContextOptions options) : base(options) { }
+ public RocketDbContext(DbContextOptions? options = null) : base(options ?? new DbContextOptions()) { }
public DbSet Rockets { get; set; } = null!;
public DbSet LaunchRecords { get; set; } = null!;
}
diff --git a/sample/Sample.Graphql/Sample.Graphql.csproj b/sample/Sample.Graphql/Sample.Graphql.csproj
index 9a8a85bfb..16b43682d 100644
--- a/sample/Sample.Graphql/Sample.Graphql.csproj
+++ b/sample/Sample.Graphql/Sample.Graphql.csproj
@@ -1,7 +1,7 @@
- netcoreapp3.1;net5.0
+ net5.0
diff --git a/src/AspNetCore.NewtonsoftJson/Conventions/NewtonsoftJsonConvention.cs b/src/AspNetCore.NewtonsoftJson/Conventions/NewtonsoftJsonConvention.cs
index 9b5bdd782..67c0ef86f 100644
--- a/src/AspNetCore.NewtonsoftJson/Conventions/NewtonsoftJsonConvention.cs
+++ b/src/AspNetCore.NewtonsoftJson/Conventions/NewtonsoftJsonConvention.cs
@@ -11,6 +11,7 @@
using Rocket.Surgery.Conventions;
using Rocket.Surgery.Conventions.DependencyInjection;
using Rocket.Surgery.LaunchPad.AspNetCore.NewtonsoftJson.Conventions;
+using Rocket.Surgery.LaunchPad.Foundation;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -28,6 +29,12 @@ namespace Rocket.Surgery.LaunchPad.AspNetCore.NewtonsoftJson.Conventions
[PublicAPI]
public class NewtonsoftJsonConvention : IServiceConvention
{
+ private readonly FoundationOptions _options;
+
+ public NewtonsoftJsonConvention(FoundationOptions? options = null)
+ {
+ _options = options ?? new();
+ }
///
/// Registers the specified context.
///
@@ -45,111 +52,9 @@ public void Register(IConventionContext context, IConfiguration configuration, I
services.Configure(
options =>
{
- options.SerializerSettings.Converters.Add(new StringEnumConverter(new CamelCaseNamingStrategy()));
- options.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- InstantPattern.ExtendedIso,
- InstantPattern.General,
- new DateTimeOffsetPattern(),
- new DateTimePattern()
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- LocalDatePattern.Iso,
- LocalDatePattern.FullRoundtrip
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- LocalDateTimePattern.ExtendedIso,
- LocalDateTimePattern.GeneralIso,
- LocalDateTimePattern.BclRoundtrip,
- LocalDateTimePattern.FullRoundtrip,
- LocalDateTimePattern.FullRoundtripWithoutCalendar
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- LocalTimePattern.ExtendedIso,
- LocalTimePattern.GeneralIso,
- LocalTimePattern.LongExtendedIso
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- OffsetPattern.GeneralInvariant,
- OffsetPattern.GeneralInvariantWithZ
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- DurationPattern.JsonRoundtrip,
- DurationPattern.Roundtrip
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- DurationPattern.JsonRoundtrip,
- DurationPattern.Roundtrip
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- PeriodPattern.Roundtrip,
- PeriodPattern.NormalizingIso
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- OffsetDateTimePattern.GeneralIso,
- OffsetDateTimePattern.FullRoundtrip
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- OffsetDatePattern.GeneralIso,
- OffsetDatePattern.FullRoundtrip
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- OffsetTimePattern.Rfc3339,
- OffsetTimePattern.GeneralIso,
- OffsetTimePattern.ExtendedIso
- )
- );
- ReplaceConverter(
- options.SerializerSettings.Converters,
- new CompositeNodaPatternConverter(
- ZonedDateTimePattern.CreateWithInvariantCulture("uuuu'-'MM'-'dd'T'HH':'mm':'ss;FFFFFFFFFo z", DateTimeZoneProviders.Tzdb),
- ZonedDateTimePattern.ExtendedFormatOnlyIso,
- ZonedDateTimePattern.GeneralFormatOnlyIso
- )
- );
+ options.SerializerSettings.ConfigureForLaunchPad(_options.DateTimeZoneProvider);
}
);
}
-
- private static void ReplaceConverter(ICollection converters, CompositeNodaPatternConverter converter)
- {
- foreach (var c in converters.Where(z => z.CanConvert(typeof(T))).ToArray())
- {
- converters.Remove(c);
- }
- converters.Add(converter);
- }
}
}
\ No newline at end of file
diff --git a/src/AspNetCore.NewtonsoftJson/DateTimeOffsetPattern.cs b/src/AspNetCore.NewtonsoftJson/DateTimeOffsetPattern.cs
deleted file mode 100644
index fc2930ef8..000000000
--- a/src/AspNetCore.NewtonsoftJson/DateTimeOffsetPattern.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using NodaTime;
-using NodaTime.Extensions;
-using NodaTime.Text;
-using System;
-using System.Text;
-
-namespace Rocket.Surgery.LaunchPad.AspNetCore.NewtonsoftJson
-{
- class DateTimeOffsetPattern : IPattern
- {
- public ParseResult Parse(string text) => DateTimeOffset.TryParse(text, out var value)
- ? ParseResult.ForValue(value.ToInstant())
- : ParseResult.ForException(() => new FormatException("Could not parse DateTimeOffset"));
-
- public string Format(Instant value) => InstantPattern.ExtendedIso.Format(value);
- public StringBuilder AppendFormat(Instant value, StringBuilder builder) => InstantPattern.ExtendedIso.AppendFormat(value, builder);
- }
-}
\ No newline at end of file
diff --git a/src/AspNetCore.NewtonsoftJson/DateTimePattern.cs b/src/AspNetCore.NewtonsoftJson/DateTimePattern.cs
deleted file mode 100644
index b1693249e..000000000
--- a/src/AspNetCore.NewtonsoftJson/DateTimePattern.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using NodaTime;
-using NodaTime.Extensions;
-using NodaTime.Text;
-using System;
-using System.Text;
-
-namespace Rocket.Surgery.LaunchPad.AspNetCore.NewtonsoftJson
-{
- class DateTimePattern : IPattern
- {
- public ParseResult Parse(string text) => DateTime.TryParse(text, out var value)
- ? ParseResult.ForValue(value.ToInstant())
- : ParseResult.ForException(() => new FormatException("Could not parse DateTimeOffset"));
-
- public string Format(Instant value) => InstantPattern.ExtendedIso.Format(value);
- public StringBuilder AppendFormat(Instant value, StringBuilder builder) => InstantPattern.ExtendedIso.AppendFormat(value, builder);
- }
-}
\ No newline at end of file
diff --git a/src/AspNetCore/Conventions/SystemJsonTextConvention.cs b/src/AspNetCore/Conventions/SystemJsonTextConvention.cs
index 421f92289..8a09824b6 100644
--- a/src/AspNetCore/Conventions/SystemJsonTextConvention.cs
+++ b/src/AspNetCore/Conventions/SystemJsonTextConvention.cs
@@ -12,6 +12,7 @@
using Rocket.Surgery.Conventions;
using Rocket.Surgery.Conventions.DependencyInjection;
using Rocket.Surgery.LaunchPad.AspNetCore.Conventions;
+using Rocket.Surgery.LaunchPad.Foundation;
using System.Collections.Generic;
using System.Linq;
using JsonConverter = System.Text.Json.Serialization.JsonConverter;
@@ -30,6 +31,12 @@ namespace Rocket.Surgery.LaunchPad.AspNetCore.Conventions
[PublicAPI]
public class SystemJsonTextConvention : IServiceConvention
{
+ private readonly FoundationOptions _options;
+
+ public SystemJsonTextConvention(FoundationOptions? options = null)
+ {
+ _options = options ?? new();
+ }
///
/// Registers the specified context.
///
@@ -44,105 +51,9 @@ public void Register(IConventionContext context, IConfiguration configuration, I
services.Configure(
options =>
{
- options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
- options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
- options.JsonSerializerOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- InstantPattern.General,
- InstantPattern.ExtendedIso,
- new DateTimeOffsetPattern(),
- new DateTimePattern()
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- LocalDatePattern.Iso,
- LocalDatePattern.FullRoundtrip
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- LocalDateTimePattern.GeneralIso,
- LocalDateTimePattern.ExtendedIso,
- LocalDateTimePattern.BclRoundtrip,
- LocalDateTimePattern.FullRoundtrip,
- LocalDateTimePattern.FullRoundtripWithoutCalendar
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- LocalTimePattern.ExtendedIso,
- LocalTimePattern.GeneralIso,
- LocalTimePattern.LongExtendedIso
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- OffsetPattern.GeneralInvariant,
- OffsetPattern.GeneralInvariantWithZ
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- DurationPattern.JsonRoundtrip,
- DurationPattern.Roundtrip
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- PeriodPattern.Roundtrip,
- PeriodPattern.NormalizingIso
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- OffsetDateTimePattern.GeneralIso,
- OffsetDateTimePattern.FullRoundtrip
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- OffsetDatePattern.GeneralIso,
- OffsetDatePattern.FullRoundtrip
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- OffsetTimePattern.Rfc3339,
- OffsetTimePattern.GeneralIso,
- OffsetTimePattern.ExtendedIso
- )
- );
- ReplaceConverter(
- options.JsonSerializerOptions.Converters,
- new CompositeNodaPatternConverter(
- ZonedDateTimePattern.CreateWithInvariantCulture("uuuu'-'MM'-'dd'T'HH':'mm':'ss;FFFFFFFFFo z", DateTimeZoneProviders.Tzdb),
- ZonedDateTimePattern.ExtendedFormatOnlyIso,
- ZonedDateTimePattern.GeneralFormatOnlyIso
- )
- );
+ options.JsonSerializerOptions.ConfigureForLaunchPad(_options.DateTimeZoneProvider);
}
);
}
-
- private static void ReplaceConverter(ICollection converters, CompositeNodaPatternConverter converter)
- {
- foreach (var c in converters.Where(z => z.CanConvert(typeof(T))).ToArray())
- {
- converters.Remove(c);
- }
- converters.Add(converter);
- }
}
}
\ No newline at end of file
diff --git a/src/AspNetCore/Rocket.Surgery.LaunchPad.AspNetCore.csproj b/src/AspNetCore/Rocket.Surgery.LaunchPad.AspNetCore.csproj
index 28d81e0cd..3039e8926 100644
--- a/src/AspNetCore/Rocket.Surgery.LaunchPad.AspNetCore.csproj
+++ b/src/AspNetCore/Rocket.Surgery.LaunchPad.AspNetCore.csproj
@@ -16,7 +16,4 @@
-
-
-
diff --git a/src/EntityFramework.HotChocolate/Rocket.Surgery.LaunchPad.EntityFramework.HotChocolate.csproj b/src/EntityFramework.HotChocolate/Rocket.Surgery.LaunchPad.EntityFramework.HotChocolate.csproj
index bff941bdc..d9a0fbbf4 100644
--- a/src/EntityFramework.HotChocolate/Rocket.Surgery.LaunchPad.EntityFramework.HotChocolate.csproj
+++ b/src/EntityFramework.HotChocolate/Rocket.Surgery.LaunchPad.EntityFramework.HotChocolate.csproj
@@ -1,6 +1,6 @@
- netstandard2.1;net5.0
+ net5.0
$(PackageTags)
diff --git a/src/AspNetCore.NewtonsoftJson/CompositeNodaPatternConverter.cs b/src/Foundation.NewtonsoftJson/NewtonsoftJsonCompositeNodaPatternConverter.cs
similarity index 88%
rename from src/AspNetCore.NewtonsoftJson/CompositeNodaPatternConverter.cs
rename to src/Foundation.NewtonsoftJson/NewtonsoftJsonCompositeNodaPatternConverter.cs
index b5380140e..eb494ec73 100644
--- a/src/AspNetCore.NewtonsoftJson/CompositeNodaPatternConverter.cs
+++ b/src/Foundation.NewtonsoftJson/NewtonsoftJsonCompositeNodaPatternConverter.cs
@@ -4,14 +4,14 @@
using NodaTime.Utility;
using System;
-namespace Rocket.Surgery.LaunchPad.AspNetCore.NewtonsoftJson
+namespace Rocket.Surgery.LaunchPad.Foundation
{
///
/// A JSON converter for types which can be represented by a single string value, parsed or formatted
/// from an .
///
/// The type to convert to/from JSON.
- public sealed class CompositeNodaPatternConverter : NodaConverterBase
+ public sealed class NewtonsoftJsonCompositeNodaPatternConverter : NodaConverterBase
{
private readonly IPattern[] _patterns;
private readonly Action? _validator;
@@ -20,7 +20,7 @@ public sealed class CompositeNodaPatternConverter : NodaConverterBase
/// Creates a new instance with a pattern and no validator.
///
/// The patterns to use for parsing and formatting.
- public CompositeNodaPatternConverter(params IPattern[] patterns) : this(null, patterns) { }
+ public NewtonsoftJsonCompositeNodaPatternConverter(params IPattern[] patterns) : this(null, patterns) { }
///
/// Creates a new instance with a pattern and an optional validator. The validator will be called before each
@@ -28,7 +28,7 @@ public CompositeNodaPatternConverter(params IPattern[] patterns) : this(null,
///
/// The patterns to use for parsing and formatting.
/// The validator to call before writing values. May be null, indicating that no validation is required.
- public CompositeNodaPatternConverter(Action? validator, params IPattern[] patterns)
+ public NewtonsoftJsonCompositeNodaPatternConverter(Action? validator, params IPattern[] patterns)
{
this._patterns = patterns;
this._validator = validator;
diff --git a/src/AspNetCore/DateTimeOffsetPattern.cs b/src/Foundation.NewtonsoftJson/NewtonsoftJsonDateTimeOffsetPattern.cs
similarity index 84%
rename from src/AspNetCore/DateTimeOffsetPattern.cs
rename to src/Foundation.NewtonsoftJson/NewtonsoftJsonDateTimeOffsetPattern.cs
index 8600d080f..07e471da0 100644
--- a/src/AspNetCore/DateTimeOffsetPattern.cs
+++ b/src/Foundation.NewtonsoftJson/NewtonsoftJsonDateTimeOffsetPattern.cs
@@ -4,9 +4,9 @@
using System;
using System.Text;
-namespace Rocket.Surgery.LaunchPad.AspNetCore
+namespace Rocket.Surgery.LaunchPad.Foundation
{
- class DateTimeOffsetPattern : IPattern
+ class NewtonsoftJsonDateTimeOffsetPattern : IPattern
{
public ParseResult Parse(string text) => DateTimeOffset.TryParse(text, out var value)
? ParseResult.ForValue(value.ToInstant())
diff --git a/src/Foundation.NewtonsoftJson/NodaTimeNewtonsoftSerializationExtensions.cs b/src/Foundation.NewtonsoftJson/NodaTimeNewtonsoftSerializationExtensions.cs
new file mode 100644
index 000000000..28dc4e49d
--- /dev/null
+++ b/src/Foundation.NewtonsoftJson/NodaTimeNewtonsoftSerializationExtensions.cs
@@ -0,0 +1,133 @@
+using JetBrains.Annotations;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+using NodaTime;
+using NodaTime.Serialization.JsonNet;
+using NodaTime.Text;
+using Rocket.Surgery.LaunchPad.AspNetCore;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Rocket.Surgery.LaunchPad.Foundation
+{
+ ///
+ /// Extensions for noda time
+ ///
+ [PublicAPI]
+ public static class NodaTimeSerializationExtensions
+ {
+ ///
+ /// Configure System.Text.Json with defaults for launchpad
+ ///
+ ///
+ ///
+ ///
+ public static JsonSerializerSettings ConfigureForLaunchPad(this JsonSerializerSettings options, IDateTimeZoneProvider dateTimeZoneProvider)
+ {
+ options.Converters.Add(new StringEnumConverter(new CamelCaseNamingStrategy()));
+ options.ConfigureForNodaTime(dateTimeZoneProvider);
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ InstantPattern.ExtendedIso,
+ InstantPattern.General,
+ new NewtonsoftJsonDateTimeOffsetPattern()
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ LocalDatePattern.Iso,
+ LocalDatePattern.FullRoundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ LocalDateTimePattern.ExtendedIso,
+ LocalDateTimePattern.GeneralIso,
+ LocalDateTimePattern.BclRoundtrip,
+ LocalDateTimePattern.FullRoundtrip,
+ LocalDateTimePattern.FullRoundtripWithoutCalendar
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ LocalTimePattern.ExtendedIso,
+ LocalTimePattern.GeneralIso,
+ LocalTimePattern.LongExtendedIso
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ OffsetPattern.GeneralInvariant,
+ OffsetPattern.GeneralInvariantWithZ
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ DurationPattern.JsonRoundtrip,
+ DurationPattern.Roundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ DurationPattern.JsonRoundtrip,
+ DurationPattern.Roundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ PeriodPattern.Roundtrip,
+ PeriodPattern.NormalizingIso
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ OffsetDateTimePattern.GeneralIso,
+ OffsetDateTimePattern.FullRoundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ OffsetDatePattern.GeneralIso,
+ OffsetDatePattern.FullRoundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ OffsetTimePattern.Rfc3339,
+ OffsetTimePattern.GeneralIso,
+ OffsetTimePattern.ExtendedIso
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new NewtonsoftJsonCompositeNodaPatternConverter(
+ ZonedDateTimePattern.CreateWithInvariantCulture("uuuu'-'MM'-'dd'T'HH':'mm':'ss;FFFFFFFFFo z", DateTimeZoneProviders.Tzdb)
+ )
+ );
+
+ return options;
+ }
+
+ private static void ReplaceConverter(ICollection converters, NewtonsoftJsonCompositeNodaPatternConverter converter)
+ {
+ foreach (var c in converters.Where(z => z.CanConvert(typeof(T))).ToArray())
+ {
+ converters.Remove(c);
+ }
+
+ converters.Add(converter);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Foundation.NewtonsoftJson/Rocket.Surgery.LaunchPad.Foundation.NewtonsoftJson.csproj b/src/Foundation.NewtonsoftJson/Rocket.Surgery.LaunchPad.Foundation.NewtonsoftJson.csproj
index 7c6297fc4..48c423640 100644
--- a/src/Foundation.NewtonsoftJson/Rocket.Surgery.LaunchPad.Foundation.NewtonsoftJson.csproj
+++ b/src/Foundation.NewtonsoftJson/Rocket.Surgery.LaunchPad.Foundation.NewtonsoftJson.csproj
@@ -3,12 +3,13 @@
netstandard2.1;net5.0
$(PackageTags)
+ Rocket.Surgery.LaunchPad.Foundation
-
+
-
-
+
+
diff --git a/src/Foundation/Conventions/FluentValidationConvention.cs b/src/Foundation/Conventions/FluentValidationConvention.cs
index 860ddf3e2..aadf70582 100644
--- a/src/Foundation/Conventions/FluentValidationConvention.cs
+++ b/src/Foundation/Conventions/FluentValidationConvention.cs
@@ -24,6 +24,12 @@ namespace Rocket.Surgery.LaunchPad.Foundation.Conventions
[AfterConvention(typeof(MediatRConvention))]
public class FluentValidationConvention : IServiceConvention
{
+ private readonly FoundationOptions _options;
+
+ public FluentValidationConvention(FoundationOptions? options = null)
+ {
+ _options = options ?? new FoundationOptions();
+ }
///
/// Registers the specified context.
///
@@ -37,17 +43,16 @@ public void Register(IConventionContext context, IConfiguration configuration, I
throw new ArgumentNullException(nameof(context));
}
- var lifetime = context.Get()!.Lifetime!;
var assemblies = context
.AssemblyCandidateFinder
.GetCandidateAssemblies("FluentValidation");
foreach (var item in new AssemblyScanner(assemblies.SelectMany(z => z.DefinedTypes).Select(x => x.AsType())))
{
- services.TryAddEnumerable(new ServiceDescriptor(item.InterfaceType, item.ValidatorType, lifetime));
+ services.TryAddEnumerable(new ServiceDescriptor(item.InterfaceType, item.ValidatorType, _options.ValidationLifetime));
}
services.TryAddSingleton();
- services.TryAddEnumerable(new ServiceDescriptor(typeof(IPipelineBehavior<,>), typeof(ValidationPipelineBehavior<,>), lifetime));
+ services.TryAddEnumerable(new ServiceDescriptor(typeof(IPipelineBehavior<,>), typeof(ValidationPipelineBehavior<,>), _options.MediatorLifetime));
}
}
}
\ No newline at end of file
diff --git a/src/Foundation/Conventions/MediatRConvention.cs b/src/Foundation/Conventions/MediatRConvention.cs
index 993457b86..227cac8a5 100644
--- a/src/Foundation/Conventions/MediatRConvention.cs
+++ b/src/Foundation/Conventions/MediatRConvention.cs
@@ -6,6 +6,7 @@
using Rocket.Surgery.Conventions.DependencyInjection;
using Rocket.Surgery.Conventions.Reflection;
using Rocket.Surgery.LaunchPad.Foundation.Conventions;
+using System;
using System.Linq;
[assembly: Convention(typeof(MediatRConvention))]
@@ -19,21 +20,41 @@ namespace Rocket.Surgery.LaunchPad.Foundation.Conventions
///
public class MediatRConvention : IServiceConvention
{
+ private readonly FoundationOptions _options;
+
+ public MediatRConvention(FoundationOptions? options = null)
+ {
+ _options = options ?? new FoundationOptions();
+ }
+
///
/// Registers the specified context.
///
/// The context.
public void Register(IConventionContext context, IConfiguration configuration, IServiceCollection services)
{
- var serviceConfig = context.GetOrAdd(() => new MediatRServiceConfiguration());
- context.Set(serviceConfig);
-
- var assemblies = context.AssemblyCandidateFinder
- .GetCandidateAssemblies(nameof(MediatR))
- .ToArray();
-
- ServiceRegistrar.AddRequiredServices(services, serviceConfig);
- ServiceRegistrar.AddMediatRClasses(services, assemblies);
+ services.AddMediatR(
+ c =>
+ {
+ switch (_options.MediatorLifetime)
+ {
+ case ServiceLifetime.Singleton:
+ c.AsSingleton();
+ break;
+ case ServiceLifetime.Scoped:
+ c.AsScoped();
+ break;
+ case ServiceLifetime.Transient:
+ c.AsTransient();
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ },
+ context.AssemblyCandidateFinder
+ .GetCandidateAssemblies(nameof(MediatR))
+ .ToArray()
+ );
}
}
}
\ No newline at end of file
diff --git a/src/Foundation/Conventions/NodaTimeConvention.cs b/src/Foundation/Conventions/NodaTimeConvention.cs
index 4febc0056..9e8da1ed5 100644
--- a/src/Foundation/Conventions/NodaTimeConvention.cs
+++ b/src/Foundation/Conventions/NodaTimeConvention.cs
@@ -1,6 +1,7 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
using NodaTime;
using NodaTime.TimeZones;
using Rocket.Surgery.Conventions;
@@ -20,6 +21,12 @@ namespace Rocket.Surgery.LaunchPad.Foundation.Conventions
[LiveConvention]
public class NodaTimeConvention : IServiceConvention
{
+ private readonly FoundationOptions _options;
+
+ public NodaTimeConvention(FoundationOptions? options = null)
+ {
+ _options = options ?? new FoundationOptions();
+ }
///
/// Registers the specified context.
///
@@ -31,9 +38,9 @@ public void Register(IConventionContext context, IConfiguration configuration, I
throw new ArgumentNullException(nameof(context));
}
- services.AddSingleton(SystemClock.Instance);
- services.AddSingleton();
- services.AddSingleton(TzdbDateTimeZoneSource.Default);
+ services.TryAddSingleton(SystemClock.Instance);
+ services.TryAddSingleton();
+ services.TryAddSingleton(_options.DateTimeZoneSource);
}
}
}
\ No newline at end of file
diff --git a/src/Foundation/FoundationOptions.cs b/src/Foundation/FoundationOptions.cs
index 282c60154..aa7a3e299 100644
--- a/src/Foundation/FoundationOptions.cs
+++ b/src/Foundation/FoundationOptions.cs
@@ -1,4 +1,8 @@
using JetBrains.Annotations;
+using Microsoft.Extensions.DependencyInjection;
+using NodaTime;
+using NodaTime.TimeZones;
+using System.Collections.Generic;
using System.Reflection;
namespace Rocket.Surgery.LaunchPad.Foundation
@@ -16,5 +20,25 @@ public class FoundationOptions
/// Useful so that applications and conventions can know the "true" executing assembly when running in an environment like azure functions
///
public Assembly? EntryAssembly { get; set; } = null!;
+
+ ///
+ /// The NodaTime timezone source
+ ///
+ public IDateTimeZoneProvider DateTimeZoneProvider { get; set; } = DateTimeZoneProviders.Tzdb;
+
+ ///
+ /// The NodaTime timezone source
+ ///
+ public IDateTimeZoneSource DateTimeZoneSource { get; set; } = TzdbDateTimeZoneSource.Default;
+
+ ///
+ /// The Mediator lifetime
+ ///
+ public ServiceLifetime MediatorLifetime { get; set; } = ServiceLifetime.Transient;
+
+ ///
+ /// The lifetime for validation services
+ ///
+ public ServiceLifetime ValidationLifetime { get; set; } = ServiceLifetime.Transient;
}
}
\ No newline at end of file
diff --git a/src/Foundation/NodaTimeSystemTextJsonSerializationExtensions.cs b/src/Foundation/NodaTimeSystemTextJsonSerializationExtensions.cs
new file mode 100644
index 000000000..f50bf4d5e
--- /dev/null
+++ b/src/Foundation/NodaTimeSystemTextJsonSerializationExtensions.cs
@@ -0,0 +1,126 @@
+using JetBrains.Annotations;
+using NodaTime;
+using NodaTime.Serialization.SystemTextJson;
+using NodaTime.Text;
+using Rocket.Surgery.LaunchPad.AspNetCore;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Rocket.Surgery.LaunchPad.Foundation
+{
+ ///
+ /// Extensions for noda time
+ ///
+ [PublicAPI]
+ public static class NodaTimeSystemTextJsonSerializationExtensions
+ {
+ ///
+ /// Configure System.Text.Json with defaults for launchpad
+ ///
+ ///
+ ///
+ ///
+ public static JsonSerializerOptions ConfigureForLaunchPad(this JsonSerializerOptions options, IDateTimeZoneProvider dateTimeZoneProvider)
+ {
+ options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
+ options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+ options.ConfigureForNodaTime(dateTimeZoneProvider);
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ InstantPattern.General,
+ InstantPattern.ExtendedIso,
+ new SystemTextJsonDateTimeOffsetPattern()
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ LocalDatePattern.Iso,
+ LocalDatePattern.FullRoundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ LocalDateTimePattern.GeneralIso,
+ LocalDateTimePattern.ExtendedIso,
+ LocalDateTimePattern.BclRoundtrip,
+ LocalDateTimePattern.FullRoundtrip,
+ LocalDateTimePattern.FullRoundtripWithoutCalendar
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ LocalTimePattern.ExtendedIso,
+ LocalTimePattern.GeneralIso,
+ LocalTimePattern.LongExtendedIso
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ OffsetPattern.GeneralInvariant,
+ OffsetPattern.GeneralInvariantWithZ
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ DurationPattern.JsonRoundtrip,
+ DurationPattern.Roundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ PeriodPattern.Roundtrip,
+ PeriodPattern.NormalizingIso
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ OffsetDateTimePattern.GeneralIso,
+ OffsetDateTimePattern.FullRoundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ OffsetDatePattern.GeneralIso,
+ OffsetDatePattern.FullRoundtrip
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ OffsetTimePattern.Rfc3339,
+ OffsetTimePattern.GeneralIso,
+ OffsetTimePattern.ExtendedIso
+ )
+ );
+ ReplaceConverter(
+ options.Converters,
+ new SystemTextJsonCompositeNodaPatternConverter(
+ ZonedDateTimePattern.CreateWithInvariantCulture("uuuu'-'MM'-'dd'T'HH':'mm':'ss;FFFFFFFFFo z", DateTimeZoneProviders.Tzdb)
+ )
+ );
+
+ return options;
+ }
+
+ private static void ReplaceConverter(ICollection converters, SystemTextJsonCompositeNodaPatternConverter converter)
+ {
+ foreach (var c in converters.Where(z => z.CanConvert(typeof(T))).ToArray())
+ {
+ converters.Remove(c);
+ }
+
+ converters.Add(converter);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/AspNetCore/CompositeNodaPatternConverter.cs b/src/Foundation/SystemTextJsonCompositeNodaPatternConverter.cs
similarity index 84%
rename from src/AspNetCore/CompositeNodaPatternConverter.cs
rename to src/Foundation/SystemTextJsonCompositeNodaPatternConverter.cs
index b4c5607d9..435cb9310 100644
--- a/src/AspNetCore/CompositeNodaPatternConverter.cs
+++ b/src/Foundation/SystemTextJsonCompositeNodaPatternConverter.cs
@@ -3,14 +3,14 @@
using System;
using System.Text.Json;
-namespace Rocket.Surgery.LaunchPad.AspNetCore
+namespace Rocket.Surgery.LaunchPad.Foundation
{
///
/// A JSON converter for types which can be represented by a single string value, parsed or formatted
/// from an .
///
/// The type to convert to/from JSON.
- public sealed class CompositeNodaPatternConverter : NodaConverterBase
+ public sealed class SystemTextJsonCompositeNodaPatternConverter : NodaConverterBase
{
private readonly IPattern[] _patterns;
private readonly Action? _validator;
@@ -19,7 +19,7 @@ public sealed class CompositeNodaPatternConverter : NodaConverterBase
/// Creates a new instance with a pattern and no validator.
///
/// The patterns to use for parsing and formatting.
- public CompositeNodaPatternConverter(params IPattern[] patterns) : this(null, patterns) { }
+ public SystemTextJsonCompositeNodaPatternConverter(params IPattern[] patterns) : this(null, patterns) { }
///
/// Creates a new instance with a pattern and an optional validator. The validator will be called before each
@@ -27,7 +27,7 @@ public CompositeNodaPatternConverter(params IPattern[] patterns) : this(null,
///
/// The patterns to use for parsing and formatting.
/// The validator to call before writing values. May be null, indicating that no validation is required.
- public CompositeNodaPatternConverter(Action? validator, params IPattern[] patterns)
+ public SystemTextJsonCompositeNodaPatternConverter(Action? validator, params IPattern[] patterns)
{
this._patterns = patterns;
this._validator = validator;
diff --git a/src/AspNetCore/DateTimePattern.cs b/src/Foundation/SystemTextJsonDateTimeOffsetPattern.cs
similarity index 63%
rename from src/AspNetCore/DateTimePattern.cs
rename to src/Foundation/SystemTextJsonDateTimeOffsetPattern.cs
index 9ba673223..ca66ea9e7 100644
--- a/src/AspNetCore/DateTimePattern.cs
+++ b/src/Foundation/SystemTextJsonDateTimeOffsetPattern.cs
@@ -6,13 +6,13 @@
namespace Rocket.Surgery.LaunchPad.AspNetCore
{
- class DateTimePattern : IPattern
+ class SystemTextJsonDateTimeOffsetPattern : IPattern
{
- public ParseResult Parse(string text) => DateTime.TryParse(text, out var value)
+ public ParseResult Parse(string text) => DateTimeOffset.TryParse(text, out var value)
? ParseResult.ForValue(value.ToInstant())
: ParseResult.ForException(() => new FormatException("Could not parse DateTimeOffset"));
- public string Format(Instant value) => InstantPattern.ExtendedIso.Format(value);
- public StringBuilder AppendFormat(Instant value, StringBuilder builder) => InstantPattern.ExtendedIso.AppendFormat(value, builder);
+ public string Format(Instant value) => InstantPattern.General.Format(value);
+ public StringBuilder AppendFormat(Instant value, StringBuilder builder) => InstantPattern.General.AppendFormat(value, builder);
}
}
\ No newline at end of file
diff --git a/src/Mapping.NewtonsoftJson/AutoMapperConvention.cs b/src/Mapping.NewtonsoftJson/AutoMapperNewtonsoftJsonConvention.cs
similarity index 100%
rename from src/Mapping.NewtonsoftJson/AutoMapperConvention.cs
rename to src/Mapping.NewtonsoftJson/AutoMapperNewtonsoftJsonConvention.cs
diff --git a/src/Mapping.NewtonsoftJson/Rocket.Surgery.LaunchPad.Mapping.NewtonsoftJson.csproj b/src/Mapping.NewtonsoftJson/Rocket.Surgery.LaunchPad.Mapping.NewtonsoftJson.csproj
index cb2c4de14..541ffd774 100644
--- a/src/Mapping.NewtonsoftJson/Rocket.Surgery.LaunchPad.Mapping.NewtonsoftJson.csproj
+++ b/src/Mapping.NewtonsoftJson/Rocket.Surgery.LaunchPad.Mapping.NewtonsoftJson.csproj
@@ -1,13 +1,14 @@
-
- netstandard2.1;net5.0
-
- $(PackageTags)
-
-
-
-
-
-
-
+
+ netstandard2.1;net5.0
+
+ $(PackageTags)
+ Rocket.Surgery.LaunchPad.Mapping
+
+
+
+
+
+
+
diff --git a/test/Extensions.Tests/MediatRTests.cs b/test/Extensions.Tests/MediatRTests.cs
index 5bfba2467..c73df551b 100644
--- a/test/Extensions.Tests/MediatRTests.cs
+++ b/test/Extensions.Tests/MediatRTests.cs
@@ -51,8 +51,10 @@ public async Task Test2()
.UseAssemblies(new TestAssemblyProvider().GetAssemblies());
var context = ConventionContext.From(builder);
var services = new ServiceCollection();
- context.Set(new MediatRServiceConfiguration().AsSingleton());
- new MediatRConvention().Register(context, new ConfigurationBuilder().Build(), services);
+ new MediatRConvention(new FoundationOptions()
+ {
+ MediatorLifetime = ServiceLifetime.Singleton
+ }).Register(context, new ConfigurationBuilder().Build(), services);
var sub = A.Fake>();
diff --git a/test/Extensions.Tests/NewtonsoftJsonNodaTimeTests.cs b/test/Extensions.Tests/NewtonsoftJsonNodaTimeTests.cs
new file mode 100644
index 000000000..12586401e
--- /dev/null
+++ b/test/Extensions.Tests/NewtonsoftJsonNodaTimeTests.cs
@@ -0,0 +1,137 @@
+using FluentAssertions;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using NodaTime;
+using NodaTime.Text;
+using Rocket.Surgery.Extensions.Testing;
+using Rocket.Surgery.LaunchPad.Foundation;
+using Serilog;
+using System;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Extensions.Tests
+{
+ public class NewtonsoftJsonNodaTimeTests : LoggerTest
+ {
+ private JsonSerializerSettings _settings;
+
+ public NewtonsoftJsonNodaTimeTests(ITestOutputHelper outputHelper) : base(outputHelper)
+ {
+ _settings = new JsonSerializerSettings()
+ .ConfigureForLaunchPad(DateTimeZoneProviders.Tzdb);
+ }
+
+ [Theory]
+ [InlineData("2020-01-01T12:12:12Z")]
+ [InlineData("2020-01-01T12:12:12.000000000Z")]
+ [InlineData("01/01/2020 12:12:12 +00:00")]
+ public void Instant_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(Instant.FromUtc(2020, 01, 01, 12, 12, 12));
+ }
+
+ [Theory]
+ [InlineData("2020-01-01")]
+ [InlineData("2020-01-01 (ISO)")]
+ public void LocalDate_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new LocalDate(2020, 01, 01));
+ }
+
+ [Theory]
+ [InlineData("2020-01-01T12:12:12")]
+ [InlineData("2020-01-01T12:12:12.000000000")]
+ [InlineData("2020-01-01T12:12:12.0000000")]
+ [InlineData("2020-01-01T12:12:12.000000000 (ISO)")]
+ public void LocalDateTime_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new LocalDateTime(2020, 01, 01, 12, 12, 12));
+ }
+
+ [Theory]
+ [InlineData("12:12:12")]
+ [InlineData("12:12:12.0000000")]
+ [InlineData("12:12:12.000000000")]
+ public void LocalTime_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new LocalTime(12, 12, 12));
+ }
+
+ [Theory]
+ [InlineData("+03:25:45")]
+ public void Offset_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(Offset.FromTimeSpan(TimeSpan.FromSeconds(12345)));
+ }
+
+ [Theory]
+ [InlineData("3:25:45")]
+ [InlineData("0:03:25:45")]
+ public void Duration_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(Duration.FromTimeSpan(TimeSpan.FromSeconds(12345)));
+ }
+
+ [Theory]
+ [InlineData("PT12345S")]
+ [InlineData("PT3H25M45S")]
+ public void Period_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Normalize().Should()
+ .Be(Period.FromSeconds(12345).Normalize());
+ }
+
+ [Theory]
+ [InlineData("2020-01-01T12:12:12+01")]
+ [InlineData("2020-01-01T12:12:12+01 (ISO)")]
+ public void OffsetDateTime_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new OffsetDateTime(new LocalDateTime(2020, 01, 01, 12, 12, 12), Offset.FromHours(1)));
+ }
+
+ [Theory]
+ [InlineData("2020-01-01+01")]
+ [InlineData("2020-01-01+01 (ISO)")]
+ public void OffsetDate_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new OffsetDate(new LocalDate(2020, 01, 01), Offset.FromHours(1)));
+ }
+
+ [Theory]
+ [InlineData("12:12:12+01:00")]
+ [InlineData("12:12:12+01")]
+ public void OffsetTime_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new OffsetTime(new LocalTime(12, 12, 12), Offset.FromHours(1)));
+ }
+
+ [Theory]
+ [InlineData("2020-01-01T07:12:12-05 America/New_York")]
+ public void ZonedDateTime_Tests(string value)
+ {
+ JsonConvert.DeserializeObject("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new ZonedDateTime(Instant.FromUtc(2020, 01, 01, 12, 12, 12), DateTimeZoneProviders.Tzdb.GetZoneOrNull("America/New_York")));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Extensions.Tests/SystemTextJsonNodaTimeTests.cs b/test/Extensions.Tests/SystemTextJsonNodaTimeTests.cs
new file mode 100644
index 000000000..e2759241c
--- /dev/null
+++ b/test/Extensions.Tests/SystemTextJsonNodaTimeTests.cs
@@ -0,0 +1,137 @@
+using FluentAssertions;
+using Microsoft.Extensions.Logging;
+using NodaTime;
+using NodaTime.Text;
+using Rocket.Surgery.Extensions.Testing;
+using Rocket.Surgery.LaunchPad.Foundation;
+using Serilog;
+using System;
+using System.Text.Json;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Extensions.Tests
+{
+ public class SystemTextJsonNodaTimeTests : LoggerTest
+ {
+ private JsonSerializerOptions _settings;
+
+ public SystemTextJsonNodaTimeTests(ITestOutputHelper outputHelper) : base(outputHelper)
+ {
+ _settings = new JsonSerializerOptions()
+ .ConfigureForLaunchPad(DateTimeZoneProviders.Tzdb);
+ }
+
+ [Theory]
+ [InlineData("2020-01-01T12:12:12Z")]
+ [InlineData("2020-01-01T12:12:12.000000000Z")]
+ [InlineData("01/01/2020 12:12:12 +00:00")]
+ public void Instant_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(Instant.FromUtc(2020, 01, 01, 12, 12, 12));
+ }
+
+ [Theory]
+ [InlineData("2020-01-01")]
+ [InlineData("2020-01-01 (ISO)")]
+ public void LocalDate_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new LocalDate(2020, 01, 01));
+ }
+
+ [Theory]
+ [InlineData("2020-01-01T12:12:12")]
+ [InlineData("2020-01-01T12:12:12.000000000")]
+ [InlineData("2020-01-01T12:12:12.0000000")]
+ [InlineData("2020-01-01T12:12:12.000000000 (ISO)")]
+ public void LocalDateTime_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new LocalDateTime(2020, 01, 01, 12, 12, 12));
+ }
+
+ [Theory]
+ [InlineData("12:12:12")]
+ [InlineData("12:12:12.0000000")]
+ [InlineData("12:12:12.000000000")]
+ public void LocalTime_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new LocalTime(12, 12, 12));
+ }
+
+ [Theory]
+ [InlineData("+03:25:45")]
+ public void Offset_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(Offset.FromTimeSpan(TimeSpan.FromSeconds(12345)));
+ }
+
+ [Theory]
+ [InlineData("3:25:45")]
+ [InlineData("0:03:25:45")]
+ public void Duration_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(Duration.FromTimeSpan(TimeSpan.FromSeconds(12345)));
+ }
+
+ [Theory]
+ [InlineData("PT12345S")]
+ [InlineData("PT3H25M45S")]
+ public void Period_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Normalize().Should()
+ .Be(Period.FromSeconds(12345).Normalize());
+ }
+
+ [Theory]
+ [InlineData("2020-01-01T12:12:12+01")]
+ [InlineData("2020-01-01T12:12:12+01 (ISO)")]
+ public void OffsetDateTime_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new OffsetDateTime(new LocalDateTime(2020, 01, 01, 12, 12, 12), Offset.FromHours(1)));
+ }
+
+ [Theory]
+ [InlineData("2020-01-01+01")]
+ [InlineData("2020-01-01+01 (ISO)")]
+ public void OffsetDate_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new OffsetDate(new LocalDate(2020, 01, 01), Offset.FromHours(1)));
+ }
+
+ [Theory]
+ [InlineData("12:12:12+01:00")]
+ [InlineData("12:12:12+01")]
+ public void OffsetTime_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new OffsetTime(new LocalTime(12, 12, 12), Offset.FromHours(1)));
+ }
+
+ [Theory]
+ [InlineData("2020-01-01T07:12:12-05 America/New_York")]
+ public void ZonedDateTime_Tests(string value)
+ {
+ JsonSerializer.Deserialize("\"" + value + "\"", _settings)!
+ .Should()
+ .Be(new ZonedDateTime(Instant.FromUtc(2020, 01, 01, 12, 12, 12), DateTimeZoneProviders.Tzdb.GetZoneOrNull("America/New_York")));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Sample.Core.Tests/LaunchRecords/CreateLaunchRecordTests.cs b/test/Sample.Core.Tests/LaunchRecords/CreateLaunchRecordTests.cs
index ba1ac73d1..3f7278b95 100644
--- a/test/Sample.Core.Tests/LaunchRecords/CreateLaunchRecordTests.cs
+++ b/test/Sample.Core.Tests/LaunchRecords/CreateLaunchRecordTests.cs
@@ -22,18 +22,24 @@ public CreateLaunchRecordTests(ITestOutputHelper outputHelper) : base(outputHelp
[Fact]
public async Task Should_Create_A_LaunchRecord()
{
- var context = ServiceProvider.GetRequiredService();
- var rocket = new ReadyRocket()
- {
- Type = RocketType.Falcon9,
- SerialNumber = "12345678901234"
- };
- context.Add(rocket);
+ var rocket = await ServiceProvider.WithScoped()
+ .Invoke(
+ async (context, ct) =>
+ {
+ var rocket = new ReadyRocket()
+ {
+ Type = RocketType.Falcon9,
+ SerialNumber = "12345678901234"
+ };
+ context.Add(rocket);
- await context.SaveChangesAsync();
+ await context.SaveChangesAsync(ct);
+ return rocket;
+ }
+ );
var response = await ServiceProvider.WithScoped().Invoke(
- (mediator, clock) => mediator.Send(
+ async (mediator, clock, ct) => await mediator.Send(
new CreateLaunchRecord.Request()
{
Partner = "partner",
@@ -41,7 +47,8 @@ public async Task Should_Create_A_LaunchRecord()
RocketId = rocket.Id,
ScheduledLaunchDate = clock.GetCurrentInstant(),
PayloadWeightKg = 100,
- }
+ },
+ ct
)
);
diff --git a/test/Sample.Graphql.Tests/Sample.Graphql.Tests.csproj b/test/Sample.Graphql.Tests/Sample.Graphql.Tests.csproj
index 737da3ead..5df848c72 100644
--- a/test/Sample.Graphql.Tests/Sample.Graphql.Tests.csproj
+++ b/test/Sample.Graphql.Tests/Sample.Graphql.Tests.csproj
@@ -1,6 +1,6 @@
- netcoreapp3.1;net5.0
+ net5.0