diff --git a/backend/src/Squidex.Infrastructure/Commands/CommandRequest.cs b/backend/src/Squidex.Infrastructure/Commands/CommandRequest.cs new file mode 100644 index 000000000..7c4410af6 --- /dev/null +++ b/backend/src/Squidex.Infrastructure/Commands/CommandRequest.cs @@ -0,0 +1,69 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Globalization; + +namespace Squidex.Infrastructure.Commands +{ + public sealed class CommandRequest + { + public IAggregateCommand Command { get; } + + public string Culture { get; } + + public string CultureUI { get; } + + public CommandRequest(IAggregateCommand command, string culture, string cultureUI) + { + Command = command; + + Culture = culture; + CultureUI = cultureUI; + } + + public static CommandRequest Create(IAggregateCommand command) + { + return new CommandRequest(command, + CultureInfo.CurrentCulture.Name, + CultureInfo.CurrentUICulture.Name); + } + + public void ApplyContext() + { + var culture = GetCulture(Culture); + + if (culture != null) + { + CultureInfo.CurrentCulture = culture; + } + + var uiCulture = GetCulture(CultureUI); + + if (uiCulture != null) + { + CultureInfo.CurrentUICulture = uiCulture; + } + } + + private static CultureInfo? GetCulture(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + return null; + } + + try + { + return CultureInfo.GetCultureInfo(name); + } + catch (CultureNotFoundException) + { + return null; + } + } + } +} diff --git a/backend/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs b/backend/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs index ee780bf4b..0939cb1a8 100644 --- a/backend/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs +++ b/backend/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs @@ -40,11 +40,11 @@ namespace Squidex.Infrastructure.Commands return base.OnActivateAsync(key); } - public async Task> ExecuteAsync(J command, GrainContext context) + public async Task> ExecuteAsync(J request) { - context?.Use(); + request.Value.ApplyContext(); - var result = await domainObject.ExecuteAsync(command.Value); + var result = await domainObject.ExecuteAsync(request.Value.Command); return result; } diff --git a/backend/src/Squidex.Infrastructure/Commands/GrainCommandMiddleware.cs b/backend/src/Squidex.Infrastructure/Commands/GrainCommandMiddleware.cs index 60fd43e3f..f3149ec3c 100644 --- a/backend/src/Squidex.Infrastructure/Commands/GrainCommandMiddleware.cs +++ b/backend/src/Squidex.Infrastructure/Commands/GrainCommandMiddleware.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Orleans; -using Squidex.Infrastructure.Orleans; namespace Squidex.Infrastructure.Commands { @@ -43,7 +42,7 @@ namespace Squidex.Infrastructure.Commands { var grain = grainFactory.GetGrain(typedCommand.AggregateId); - var result = await grain.ExecuteAsync(typedCommand, GrainContext.Create()); + var result = await grain.ExecuteAsync(CommandRequest.Create(typedCommand)); return result.Value; } diff --git a/backend/src/Squidex.Infrastructure/Commands/IDomainObjectGrain.cs b/backend/src/Squidex.Infrastructure/Commands/IDomainObjectGrain.cs index 3a9f26e5d..4e4a4d82d 100644 --- a/backend/src/Squidex.Infrastructure/Commands/IDomainObjectGrain.cs +++ b/backend/src/Squidex.Infrastructure/Commands/IDomainObjectGrain.cs @@ -13,6 +13,6 @@ namespace Squidex.Infrastructure.Commands { public interface IDomainObjectGrain : IGrainWithGuidKey { - Task> ExecuteAsync(J command, GrainContext context); + Task> ExecuteAsync(J request); } } diff --git a/backend/src/Squidex.Infrastructure/Orleans/GrainContext.cs b/backend/src/Squidex.Infrastructure/Orleans/GrainContext.cs deleted file mode 100644 index 0b13cd809..000000000 --- a/backend/src/Squidex.Infrastructure/Orleans/GrainContext.cs +++ /dev/null @@ -1,55 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using System.Globalization; -using System.Runtime.Serialization; - -namespace Squidex.Infrastructure.Orleans -{ - [Serializable] - public class GrainContext : ISerializable - { - public CultureInfo Culture { get; private set; } - - public CultureInfo CultureUI { get; private set; } - - private GrainContext() - { - } - - protected GrainContext(SerializationInfo info, StreamingContext context) - { - Culture = CultureInfo.GetCultureInfo(info.GetString(nameof(Culture))!); - CultureUI = CultureInfo.GetCultureInfo(info.GetString(nameof(CultureUI))!); - } - - public virtual void GetObjectData(SerializationInfo info, StreamingContext context) - { - info.AddValue(nameof(Culture), Culture.Name); - info.AddValue(nameof(CultureUI), CultureUI.Name); - } - - public static GrainContext Create() - { - return new GrainContext - { - Culture = CultureInfo.CurrentCulture, - CultureUI = CultureInfo.CurrentUICulture - }; - } - - public void Use() - { - if (Culture != null) - { - CultureInfo.CurrentCulture = Culture; - CultureInfo.CurrentUICulture = CultureUI; - } - } - } -} diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs index d0f92a596..054258307 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs @@ -19,7 +19,6 @@ using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure.Assets; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Log; -using Squidex.Infrastructure.Orleans; using Squidex.Infrastructure.Reflection; using Xunit; @@ -279,7 +278,9 @@ namespace Squidex.Domain.Apps.Entities.Assets private Task ExecuteCreateAsync() { - return asset.ExecuteAsync(CreateCommand(new CreateAsset { AssetId = Id, File = file }), GrainContext.Create()); + var command = CreateCommand(new CreateAsset { AssetId = Id, File = file }); + + return asset.ExecuteAsync(CommandRequest.Create(command)); } private void AssertAssetHasBeenUploaded(long version) diff --git a/backend/tests/Squidex.Infrastructure.Tests/Orleans/GrainContextTests.cs b/backend/tests/Squidex.Infrastructure.Tests/Commands/CommandRequestTests.cs similarity index 57% rename from backend/tests/Squidex.Infrastructure.Tests/Orleans/GrainContextTests.cs rename to backend/tests/Squidex.Infrastructure.Tests/Commands/CommandRequestTests.cs index 79535e73a..16a920dc9 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Orleans/GrainContextTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Commands/CommandRequestTests.cs @@ -9,47 +9,41 @@ using System.Globalization; using System.Threading.Tasks; using Orleans; using Orleans.TestingHost; -using Squidex.Infrastructure.TestHelpers; +using Squidex.Infrastructure.Commands; using Xunit; #pragma warning disable SA1133 // Do not combine attributes -namespace Squidex.Infrastructure.Orleans +namespace Squidex.Infrastructure.Commands { - public class GrainContextTests + public class CommandRequestTests { public interface IContextGrain : IGrainWithStringKey { - Task TestAsync(GrainContext async); + Task GetCultureUIAsync(CommandRequest request); + + Task GetCultureAsync(CommandRequest request); } public class ContextGrain : Grain, IContextGrain { - public async Task TestAsync(GrainContext context) + public Task GetCultureAsync(CommandRequest request) { - await Task.Delay(100); + request.ApplyContext(); - return context; + return Task.FromResult(CultureInfo.CurrentCulture.Name); } - } - - [Fact] - public void Should_capture_culture() - { - var culture = CultureInfo.GetCultureInfo("de"); - var cultureUI = CultureInfo.GetCultureInfo("it"); - CultureInfo.CurrentCulture = culture; - CultureInfo.CurrentUICulture = cultureUI; - - var sut = GrainContext.Create(); + public Task GetCultureUIAsync(CommandRequest request) + { + request.ApplyContext(); - Assert.Same(culture, sut.Culture); - Assert.Same(cultureUI, sut.CultureUI); + return Task.FromResult(CultureInfo.CurrentUICulture.Name); + } } [Fact] - public void Should_serialize_and_deserialize() + public void Should_capture_culture() { var culture = CultureInfo.GetCultureInfo("de"); var cultureUI = CultureInfo.GetCultureInfo("it"); @@ -57,11 +51,10 @@ namespace Squidex.Infrastructure.Orleans CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = cultureUI; - var source = GrainContext.Create(); - var result = source.SerializeAndDeserializeBinary(); + var sut = CommandRequest.Create(null!); - Assert.Equal(culture, result.Culture); - Assert.Equal(cultureUI, result.CultureUI); + Assert.Same(culture.Name, sut.Culture); + Assert.Same(cultureUI.Name, sut.CultureUI); } [Fact, Trait("Category", "Dependencies")] @@ -81,11 +74,13 @@ namespace Squidex.Infrastructure.Orleans var grain = cluster.Client.GetGrain("Default"); - var source = GrainContext.Create(); - var result = await grain.TestAsync(source); + var request = CommandRequest.Create(null!); + + var cultureFromGrain = await grain.GetCultureAsync(request); + var cultureUIFromGrain = await grain.GetCultureAsync(request); - Assert.Equal(culture, result.Culture); - Assert.Equal(cultureUI, result.CultureUI); + Assert.Same(culture.Name, cultureFromGrain); + Assert.Same(cultureUI.Name, cultureUIFromGrain); } } }