From 14319cd8540ef2897220464e5a016c778ebf6c26 Mon Sep 17 00:00:00 2001 From: adimiko Date: Sun, 9 Mar 2025 20:34:27 +0100 Subject: [PATCH 1/4] Removed module from handlers --- .../EasyWay.Samples/Commands/ErrorCommand.cs | 2 +- .../Commands/ErrorCommandHandler.cs | 2 +- .../EasyWay.Samples/Commands/SampleCommand.cs | 2 +- .../Commands/SampleCommandHandler.cs | 4 ++-- .../WithResult/SampleCommandWithResult.cs | 2 +- .../SampleCommandWithResultHandler.cs | 2 +- samples/EasyWay.Samples/Program.cs | 22 +++++++++++++++++-- .../EasyWay.Samples/Queries/SampleQuery.cs | 2 +- .../Queries/SampleQueryHandler.cs | 2 +- .../Internals/WebApiResultMapper.cs | 2 +- source/EasyWay/Command.cs | 6 ++--- source/EasyWay/ICommandHandler.cs | 10 ++++----- source/EasyWay/IModuleExecutor.cs | 6 ++--- source/EasyWay/IQueryHandler.cs | 5 ++--- .../Internals/Commands/CommandExecutor.cs | 4 ++-- .../CommandWithOperationResultExecutor.cs | 4 ++-- .../EasyWay/Internals/Commands/Extensions.cs | 2 +- .../Internals/Commands/ICommandExecutor.cs | 2 +- .../ICommandWithOperationResultExecutor.cs | 2 +- .../Internals/Modules/ModuleExecutor.cs | 6 ++--- .../EasyWay/Internals/Queries/Extensions.cs | 2 +- .../Internals/Queries/IQueryExecutor.cs | 2 +- .../Internals/Queries/QueryExecutor.cs | 4 ++-- source/EasyWay/Query.cs | 3 +-- 24 files changed, 56 insertions(+), 44 deletions(-) diff --git a/samples/EasyWay.Samples/Commands/ErrorCommand.cs b/samples/EasyWay.Samples/Commands/ErrorCommand.cs index 60a9b93..66f6d13 100644 --- a/samples/EasyWay.Samples/Commands/ErrorCommand.cs +++ b/samples/EasyWay.Samples/Commands/ErrorCommand.cs @@ -1,6 +1,6 @@ namespace EasyWay.Samples.Commands { - public class ErrorCommand : Command + public class ErrorCommand : Command { } diff --git a/samples/EasyWay.Samples/Commands/ErrorCommandHandler.cs b/samples/EasyWay.Samples/Commands/ErrorCommandHandler.cs index 34cf102..d216c52 100644 --- a/samples/EasyWay.Samples/Commands/ErrorCommandHandler.cs +++ b/samples/EasyWay.Samples/Commands/ErrorCommandHandler.cs @@ -2,7 +2,7 @@ namespace EasyWay.Samples.Commands { - public class ErrorCommandHandler : ICommandHandler + public class ErrorCommandHandler : ICommandHandler { public Task Handle(ErrorCommand command) { diff --git a/samples/EasyWay.Samples/Commands/SampleCommand.cs b/samples/EasyWay.Samples/Commands/SampleCommand.cs index 8ab3a90..9f81988 100644 --- a/samples/EasyWay.Samples/Commands/SampleCommand.cs +++ b/samples/EasyWay.Samples/Commands/SampleCommand.cs @@ -1,6 +1,6 @@ namespace EasyWay.Samples.Commands { - public class SampleCommand : Command, IWithConcurrencyToken + public class SampleCommand : Command { public Guid Id { get; init; } diff --git a/samples/EasyWay.Samples/Commands/SampleCommandHandler.cs b/samples/EasyWay.Samples/Commands/SampleCommandHandler.cs index 853f412..f30454b 100644 --- a/samples/EasyWay.Samples/Commands/SampleCommandHandler.cs +++ b/samples/EasyWay.Samples/Commands/SampleCommandHandler.cs @@ -3,7 +3,7 @@ namespace EasyWay.Samples.Commands { - internal sealed class SampleCommandHandler : ICommandHandler + internal sealed class SampleCommandHandler : ICommandHandler { private readonly ICancellationContext _cancellationContext; @@ -50,7 +50,7 @@ public async Task Handle(SampleCommand command) var x = _factory.Create(); - _concurrencyTokenValidator.Validate(x, command); + //_concurrencyTokenValidator.Validate(x, command); await _repository.Add(x); diff --git a/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResult.cs b/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResult.cs index 40e741f..dd9abae 100644 --- a/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResult.cs +++ b/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResult.cs @@ -1,6 +1,6 @@ namespace EasyWay.Samples.Commands.WithResult { - public class SampleCommandWithResult : Command + public class SampleCommandWithResult : Command { public string Name { get; init; } } diff --git a/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResultHandler.cs b/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResultHandler.cs index 9e55531..daf653e 100644 --- a/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResultHandler.cs +++ b/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResultHandler.cs @@ -1,7 +1,7 @@  namespace EasyWay.Samples.Commands.WithResult { - public sealed class SampleCommandWithResultHandler : ICommandHandler + public sealed class SampleCommandWithResultHandler : ICommandHandler { public Task> Handle(SampleCommandWithResult command) { diff --git a/samples/EasyWay.Samples/Program.cs b/samples/EasyWay.Samples/Program.cs index c5b8816..673fbe3 100644 --- a/samples/EasyWay.Samples/Program.cs +++ b/samples/EasyWay.Samples/Program.cs @@ -1,4 +1,6 @@ using EasyWay.Samples; +using EasyWay.Samples.Commands; +using EasyWay.Samples.Commands.WithResult; using EasyWay.Samples.Queries; using Microsoft.AspNetCore.Mvc; @@ -14,6 +16,7 @@ await kernel builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +builder.Services.AddEasyWayWebApi(); var app = builder.Build(); @@ -25,12 +28,27 @@ await kernel app.UseHttpsRedirection(); +//app.UseEasyWay(); -app.MapPost("/query", async ([FromBody] SampleQuery query, IModuleExecutor executor) => + +app.MapPost("/query", async ([FromBody] SampleQuery query, IModuleExecutor executor, IWebApiResultMapper mapper) => +{ + var x = await executor.Execute(query); + + return mapper.Map(x); +}); + +app.MapPost("/command", async ([FromBody] SampleCommand command, IModuleExecutor executor, IWebApiResultMapper mapper) => { - return await executor.Execute(query); + return await executor.Execute(command); }); +app.MapPost("/commandwithresult", async ([FromBody] SampleCommandWithResult command, IModuleExecutor executor, IWebApiResultMapper mapper) => +{ + var x = await executor.Execute(command); + + return mapper.Map(x); +}); app.Run(); diff --git a/samples/EasyWay.Samples/Queries/SampleQuery.cs b/samples/EasyWay.Samples/Queries/SampleQuery.cs index c0a676e..bac5e71 100644 --- a/samples/EasyWay.Samples/Queries/SampleQuery.cs +++ b/samples/EasyWay.Samples/Queries/SampleQuery.cs @@ -1,6 +1,6 @@ namespace EasyWay.Samples.Queries { - public class SampleQuery : Query + public class SampleQuery : Query { public required string Name { get; init; } diff --git a/samples/EasyWay.Samples/Queries/SampleQueryHandler.cs b/samples/EasyWay.Samples/Queries/SampleQueryHandler.cs index 9f2822f..51a0fe1 100644 --- a/samples/EasyWay.Samples/Queries/SampleQueryHandler.cs +++ b/samples/EasyWay.Samples/Queries/SampleQueryHandler.cs @@ -1,6 +1,6 @@ namespace EasyWay.Samples.Queries { - public class SampleQueryHandler : IQueryHandler + public class SampleQueryHandler : IQueryHandler { public Task> Handle(SampleQuery query) { diff --git a/source/EasyWay.WebApi/Internals/WebApiResultMapper.cs b/source/EasyWay.WebApi/Internals/WebApiResultMapper.cs index de35d49..7948921 100644 --- a/source/EasyWay.WebApi/Internals/WebApiResultMapper.cs +++ b/source/EasyWay.WebApi/Internals/WebApiResultMapper.cs @@ -20,7 +20,7 @@ public IResult Map(CommandResult commandResu { return commandResult.Error switch { - CommandErrorEnum.None => Results.Ok(), + CommandErrorEnum.None => Results.Ok(commandResult.OperationResult), CommandErrorEnum.Validation => Results.BadRequest(commandResult.ValidationErrors), _ => Results.StatusCode(500), }; diff --git a/source/EasyWay/Command.cs b/source/EasyWay/Command.cs index 08eb75f..7ce2cb5 100644 --- a/source/EasyWay/Command.cs +++ b/source/EasyWay/Command.cs @@ -3,10 +3,8 @@ /// /// Represents a command /// - public abstract class Command - where TModule : EasyWayModule; + public abstract class Command; - public abstract class Command - where TModule : EasyWayModule + public abstract class Command where TCommandResult : OperationResult; } diff --git a/source/EasyWay/ICommandHandler.cs b/source/EasyWay/ICommandHandler.cs index 4e87b85..28a345f 100644 --- a/source/EasyWay/ICommandHandler.cs +++ b/source/EasyWay/ICommandHandler.cs @@ -4,9 +4,8 @@ /// Defines a handler for a command /// /// The type of command being handled - public interface ICommandHandler - where TModule : EasyWayModule - where TCommand : Command + public interface ICommandHandler + where TCommand : Command { /// /// Handles a command @@ -15,9 +14,8 @@ public interface ICommandHandler Task Handle(TCommand command); } - public interface ICommandHandler - where TModule : EasyWayModule - where TCommand : Command + public interface ICommandHandler + where TCommand : Command where TOperationResult : OperationResult { Task> Handle(TCommand command); diff --git a/source/EasyWay/IModuleExecutor.cs b/source/EasyWay/IModuleExecutor.cs index cdeb201..c0fed2b 100644 --- a/source/EasyWay/IModuleExecutor.cs +++ b/source/EasyWay/IModuleExecutor.cs @@ -4,12 +4,12 @@ public interface IModuleExecutor where TModule : EasyWayModule { Task Execute(TCommand command, CancellationToken cancellationToken = default) - where TCommand : Command; + where TCommand : Command; - Task> Execute(Command command, CancellationToken cancellationToken = default) + Task> Execute(Command command, CancellationToken cancellationToken = default) where TOperationResult : OperationResult; - Task> Execute(Query query, CancellationToken cancellationToken = default) + Task> Execute(Query query, CancellationToken cancellationToken = default) where TReadModel : ReadModel; } } diff --git a/source/EasyWay/IQueryHandler.cs b/source/EasyWay/IQueryHandler.cs index 01295f1..0098732 100644 --- a/source/EasyWay/IQueryHandler.cs +++ b/source/EasyWay/IQueryHandler.cs @@ -6,9 +6,8 @@ namespace EasyWay /// Defines a handler for a query /// /// The type of query being handled - public interface IQueryHandler - where TModule : EasyWayModule - where TQuery : Query + public interface IQueryHandler + where TQuery : Query where TReadModel : ReadModel { /// diff --git a/source/EasyWay/Internals/Commands/CommandExecutor.cs b/source/EasyWay/Internals/Commands/CommandExecutor.cs index 77f4520..f73be7f 100644 --- a/source/EasyWay/Internals/Commands/CommandExecutor.cs +++ b/source/EasyWay/Internals/Commands/CommandExecutor.cs @@ -24,7 +24,7 @@ public CommandExecutor( } public async Task Execute(TCommand command, CancellationToken cancellationToken) - where TCommand : Command + where TCommand : Command { _cancellationContextConstructor.Set(cancellationToken); @@ -41,7 +41,7 @@ public async Task Execute(TCommand command, Cancellatio } var commandResult = await _serviceProvider - .GetRequiredService>() + .GetRequiredService>() .Handle(command); await _unitOfWorkCommandHandler.Handle(); diff --git a/source/EasyWay/Internals/Commands/CommandWithOperationResultExecutor.cs b/source/EasyWay/Internals/Commands/CommandWithOperationResultExecutor.cs index 703e971..7177cfd 100644 --- a/source/EasyWay/Internals/Commands/CommandWithOperationResultExecutor.cs +++ b/source/EasyWay/Internals/Commands/CommandWithOperationResultExecutor.cs @@ -23,7 +23,7 @@ public CommandWithOperationResultExecutor( _unitOfWorkCommandHandler = unitOfWorkCommandHandler; } - public async Task> Execute(Command command, CancellationToken cancellationToken) + public async Task> Execute(Command command, CancellationToken cancellationToken) where TOperationResult : OperationResult { _cancellationContextConstructor.Set(cancellationToken); @@ -46,7 +46,7 @@ public async Task> Execute(Com } } - var commandHandlerType = typeof(ICommandHandler<,,>).MakeGenericType(typeof(TModule), commandType, typeof(TOperationResult)); + var commandHandlerType = typeof(ICommandHandler<,>).MakeGenericType(commandType, typeof(TOperationResult)); var commandHandler = _serviceProvider.GetRequiredService(commandHandlerType); diff --git a/source/EasyWay/Internals/Commands/Extensions.cs b/source/EasyWay/Internals/Commands/Extensions.cs index 3544d8b..03a6c2f 100644 --- a/source/EasyWay/Internals/Commands/Extensions.cs +++ b/source/EasyWay/Internals/Commands/Extensions.cs @@ -19,7 +19,7 @@ internal static IServiceCollection AddCommands( .WithScopedLifetime()); services.Scan(s => s.FromAssemblies(assemblies) - .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<,,>))) + .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<>))) .AsImplementedInterfaces() .WithScopedLifetime()); diff --git a/source/EasyWay/Internals/Commands/ICommandExecutor.cs b/source/EasyWay/Internals/Commands/ICommandExecutor.cs index 49502ae..c6f64b5 100644 --- a/source/EasyWay/Internals/Commands/ICommandExecutor.cs +++ b/source/EasyWay/Internals/Commands/ICommandExecutor.cs @@ -4,6 +4,6 @@ internal interface ICommandExecutor where TModule : EasyWayModule { Task Execute(TCommand command, CancellationToken cancellationToken) - where TCommand : Command; + where TCommand : Command; } } diff --git a/source/EasyWay/Internals/Commands/ICommandWithOperationResultExecutor.cs b/source/EasyWay/Internals/Commands/ICommandWithOperationResultExecutor.cs index de7193d..e1a0719 100644 --- a/source/EasyWay/Internals/Commands/ICommandWithOperationResultExecutor.cs +++ b/source/EasyWay/Internals/Commands/ICommandWithOperationResultExecutor.cs @@ -3,7 +3,7 @@ internal interface ICommandWithOperationResultExecutor where TModule : EasyWayModule { - Task> Execute(Command command, CancellationToken cancellationToken) + Task> Execute(Command command, CancellationToken cancellationToken) where TOperationResult : OperationResult; } } diff --git a/source/EasyWay/Internals/Modules/ModuleExecutor.cs b/source/EasyWay/Internals/Modules/ModuleExecutor.cs index d1d88cc..047d36d 100644 --- a/source/EasyWay/Internals/Modules/ModuleExecutor.cs +++ b/source/EasyWay/Internals/Modules/ModuleExecutor.cs @@ -15,7 +15,7 @@ public ModuleExecutor(IServiceProvider serviceProvider) } public async Task Execute(TCommand command, CancellationToken cancellationToken = default) - where TCommand : Command + where TCommand : Command { CommandResult commandResult; @@ -31,7 +31,7 @@ public async Task Execute(TCommand command, Cancellatio return commandResult; } - public async Task> Execute(Command command, CancellationToken cancellationToken = default) + public async Task> Execute(Command command, CancellationToken cancellationToken = default) where TOperationResult : OperationResult { CommandResult commandResult; @@ -48,7 +48,7 @@ public async Task> Execute(Com return commandResult; } - public async Task> Execute(Query query, CancellationToken cancellationToken = default) + public async Task> Execute(Query query, CancellationToken cancellationToken = default) where TReadModel : ReadModel { QueryResult result; diff --git a/source/EasyWay/Internals/Queries/Extensions.cs b/source/EasyWay/Internals/Queries/Extensions.cs index 64cd50a..0a1715a 100644 --- a/source/EasyWay/Internals/Queries/Extensions.cs +++ b/source/EasyWay/Internals/Queries/Extensions.cs @@ -13,7 +13,7 @@ internal static IServiceCollection AddQueries( services.AddScoped(typeof(IQueryExecutor<>).MakeGenericType(moduleType), typeof(QueryExecutor<>).MakeGenericType(moduleType)); services.Scan(s => s.FromAssemblies(assemblies) - .AddClasses(c => c.AssignableTo(typeof(IQueryHandler<,,>))) + .AddClasses(c => c.AssignableTo(typeof(IQueryHandler<,>))) .AsImplementedInterfaces() .WithScopedLifetime()); diff --git a/source/EasyWay/Internals/Queries/IQueryExecutor.cs b/source/EasyWay/Internals/Queries/IQueryExecutor.cs index f874c59..0cc5b34 100644 --- a/source/EasyWay/Internals/Queries/IQueryExecutor.cs +++ b/source/EasyWay/Internals/Queries/IQueryExecutor.cs @@ -3,7 +3,7 @@ internal interface IQueryExecutor where TModule : EasyWayModule { - Task> Execute(Query query, CancellationToken cancellationToken) + Task> Execute(Query query, CancellationToken cancellationToken) where TReadModel : ReadModel; } } diff --git a/source/EasyWay/Internals/Queries/QueryExecutor.cs b/source/EasyWay/Internals/Queries/QueryExecutor.cs index c0cabd9..9dc89e8 100644 --- a/source/EasyWay/Internals/Queries/QueryExecutor.cs +++ b/source/EasyWay/Internals/Queries/QueryExecutor.cs @@ -19,7 +19,7 @@ public QueryExecutor( _cancellationContextConstructor = cancellationContextConstructor; } - public async Task> Execute(Query query, CancellationToken cancellationToken) + public async Task> Execute(Query query, CancellationToken cancellationToken) where TReadModel : ReadModel { _cancellationContextConstructor.Set(cancellationToken); @@ -42,7 +42,7 @@ public async Task> Execute(Query).MakeGenericType(typeof(TModule), queryType, typeof(TReadModel)); + var queryHandlerType = typeof(IQueryHandler<,>).MakeGenericType( queryType, typeof(TReadModel)); var queryHandler = _serviceProvider.GetRequiredService(queryHandlerType); diff --git a/source/EasyWay/Query.cs b/source/EasyWay/Query.cs index 54f1b6c..8508ce0 100644 --- a/source/EasyWay/Query.cs +++ b/source/EasyWay/Query.cs @@ -4,7 +4,6 @@ /// Represents a query /// /// Read model type - public abstract class Query - where TModule : EasyWayModule + public abstract class Query where TReadModel : ReadModel; } From b61daa17b2e9b5eff792f38452cf2764aa8bc8a2 Mon Sep 17 00:00:00 2001 From: adimiko Date: Sun, 9 Mar 2025 20:55:19 +0100 Subject: [PATCH 2/4] Updated ConcurrencyConflictValidator --- samples/EasyWay.Samples/Commands/SampleCommand.cs | 2 +- .../EasyWay.Samples/Commands/SampleCommandHandler.cs | 2 +- .../Commands/WithResult/SampleCommandWithResult.cs | 4 +++- samples/EasyWay.Samples/SampleModule.cs | 6 ++++-- source/EasyWay/Command.cs | 2 +- source/EasyWay/IConcurrencyConflictValidator.cs | 4 ++-- .../Internals/Commands/ConcurrencyConflictValidator.cs | 6 ++---- .../Commands/ConcurrencyConflictValidatorTests.cs | 10 +++++++++- 8 files changed, 23 insertions(+), 13 deletions(-) diff --git a/samples/EasyWay.Samples/Commands/SampleCommand.cs b/samples/EasyWay.Samples/Commands/SampleCommand.cs index 9f81988..401de8f 100644 --- a/samples/EasyWay.Samples/Commands/SampleCommand.cs +++ b/samples/EasyWay.Samples/Commands/SampleCommand.cs @@ -1,6 +1,6 @@ namespace EasyWay.Samples.Commands { - public class SampleCommand : Command + public class SampleCommand : Command, IWithConcurrencyToken { public Guid Id { get; init; } diff --git a/samples/EasyWay.Samples/Commands/SampleCommandHandler.cs b/samples/EasyWay.Samples/Commands/SampleCommandHandler.cs index f30454b..c0037fa 100644 --- a/samples/EasyWay.Samples/Commands/SampleCommandHandler.cs +++ b/samples/EasyWay.Samples/Commands/SampleCommandHandler.cs @@ -50,7 +50,7 @@ public async Task Handle(SampleCommand command) var x = _factory.Create(); - //_concurrencyTokenValidator.Validate(x, command); + _concurrencyTokenValidator.Validate(x, command); await _repository.Add(x); diff --git a/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResult.cs b/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResult.cs index dd9abae..b58e018 100644 --- a/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResult.cs +++ b/samples/EasyWay.Samples/Commands/WithResult/SampleCommandWithResult.cs @@ -1,7 +1,9 @@ namespace EasyWay.Samples.Commands.WithResult { - public class SampleCommandWithResult : Command + public class SampleCommandWithResult : Command, IWithConcurrencyToken { public string Name { get; init; } + + public short ConcurrencyToken { get; init; } } } diff --git a/samples/EasyWay.Samples/SampleModule.cs b/samples/EasyWay.Samples/SampleModule.cs index 66f0f5e..5e4a575 100644 --- a/samples/EasyWay.Samples/SampleModule.cs +++ b/samples/EasyWay.Samples/SampleModule.cs @@ -1,4 +1,5 @@ -using EasyWay.Samples.Databases; +using EasyWay.Samples.Commands; +using EasyWay.Samples.Databases; using Microsoft.EntityFrameworkCore; using System.Reflection; @@ -8,7 +9,8 @@ public sealed class SampleModule : EasyWayModule { protected override IEnumerable Assemblies => new List { - typeof(SampleModule).Assembly + typeof(SampleModule).Assembly, + typeof(SampleCommand).Assembly }; protected override void ConfigureDependencies(IServiceCollection services, IConfiguration configuration) diff --git a/source/EasyWay/Command.cs b/source/EasyWay/Command.cs index 7ce2cb5..9a5240a 100644 --- a/source/EasyWay/Command.cs +++ b/source/EasyWay/Command.cs @@ -5,6 +5,6 @@ /// public abstract class Command; - public abstract class Command + public abstract class Command : Command where TCommandResult : OperationResult; } diff --git a/source/EasyWay/IConcurrencyConflictValidator.cs b/source/EasyWay/IConcurrencyConflictValidator.cs index ff24438..4f12e41 100644 --- a/source/EasyWay/IConcurrencyConflictValidator.cs +++ b/source/EasyWay/IConcurrencyConflictValidator.cs @@ -2,7 +2,7 @@ { public interface IConcurrencyConflictValidator { - void Validate(TAggregateRoot aggregateRoot, IWithConcurrencyToken command) - where TAggregateRoot : AggregateRoot; + void Validate(AggregateRoot aggregateRoot, TCommand command) + where TCommand : Command, IWithConcurrencyToken; } } diff --git a/source/EasyWay/Internals/Commands/ConcurrencyConflictValidator.cs b/source/EasyWay/Internals/Commands/ConcurrencyConflictValidator.cs index 672fe6f..1c3eb6c 100644 --- a/source/EasyWay/Internals/Commands/ConcurrencyConflictValidator.cs +++ b/source/EasyWay/Internals/Commands/ConcurrencyConflictValidator.cs @@ -2,10 +2,8 @@ { internal sealed class ConcurrencyConflictValidator : IConcurrencyConflictValidator { - public void Validate( - TAggregateRoot aggregateRoot, - IWithConcurrencyToken command) - where TAggregateRoot : AggregateRoot + public void Validate(AggregateRoot aggregateRoot, TCommand command) + where TCommand : Command, IWithConcurrencyToken { if (aggregateRoot.ConcurrencyToken == command.ConcurrencyToken) { diff --git a/tests/EasyWay.Tests/Internals/Commands/ConcurrencyConflictValidatorTests.cs b/tests/EasyWay.Tests/Internals/Commands/ConcurrencyConflictValidatorTests.cs index 1887c54..9a48d45 100644 --- a/tests/EasyWay.Tests/Internals/Commands/ConcurrencyConflictValidatorTests.cs +++ b/tests/EasyWay.Tests/Internals/Commands/ConcurrencyConflictValidatorTests.cs @@ -10,7 +10,15 @@ public sealed class ConcurrencyConflictValidatorTests internal sealed class TestAggragate : AggregateRoot; - internal sealed record TestClass(short ConcurrencyToken) : IWithConcurrencyToken; + internal sealed class TestClass : Command, IWithConcurrencyToken + { + public short ConcurrencyToken { get; } + + public TestClass(short concurrencyToken) + { + ConcurrencyToken = concurrencyToken; + } + } [Fact(DisplayName = $"When concurrency tokens are different validator should throw {nameof(ConcurrencyException)}")] public void WhenConcurrencyTokensAreDifferent() From 0f49ba84903d4f65dc210b54071deca8ac793a16 Mon Sep 17 00:00:00 2001 From: adimiko Date: Sun, 9 Mar 2025 21:27:11 +0100 Subject: [PATCH 3/4] Changed QueryExecutor --- samples/EasyWay.Samples/Program.cs | 2 +- source/Directory.Packages.props | 16 ++++++++-------- source/EasyWay/IModuleExecutor.cs | 3 ++- source/EasyWay/Internals/Commands/Extensions.cs | 8 ++++---- .../EasyWay/Internals/Modules/ModuleExecutor.cs | 5 +++-- .../EasyWay/Internals/Queries/IQueryExecutor.cs | 3 ++- .../EasyWay/Internals/Queries/QueryExecutor.cs | 15 ++++++--------- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/samples/EasyWay.Samples/Program.cs b/samples/EasyWay.Samples/Program.cs index 673fbe3..c233009 100644 --- a/samples/EasyWay.Samples/Program.cs +++ b/samples/EasyWay.Samples/Program.cs @@ -33,7 +33,7 @@ await kernel app.MapPost("/query", async ([FromBody] SampleQuery query, IModuleExecutor executor, IWebApiResultMapper mapper) => { - var x = await executor.Execute(query); + var x = await executor.Execute(query); return mapper.Map(x); }); diff --git a/source/Directory.Packages.props b/source/Directory.Packages.props index 3b0bd91..a795e54 100644 --- a/source/Directory.Packages.props +++ b/source/Directory.Packages.props @@ -7,15 +7,15 @@ - - - - - - + + + + + + - + - + \ No newline at end of file diff --git a/source/EasyWay/IModuleExecutor.cs b/source/EasyWay/IModuleExecutor.cs index c0fed2b..2031f7b 100644 --- a/source/EasyWay/IModuleExecutor.cs +++ b/source/EasyWay/IModuleExecutor.cs @@ -9,7 +9,8 @@ Task Execute(TCommand command, CancellationToken cancel Task> Execute(Command command, CancellationToken cancellationToken = default) where TOperationResult : OperationResult; - Task> Execute(Query query, CancellationToken cancellationToken = default) + Task> Execute(TQuery query, CancellationToken cancellationToken = default) + where TQuery : Query where TReadModel : ReadModel; } } diff --git a/source/EasyWay/Internals/Commands/Extensions.cs b/source/EasyWay/Internals/Commands/Extensions.cs index 03a6c2f..94aeb8a 100644 --- a/source/EasyWay/Internals/Commands/Extensions.cs +++ b/source/EasyWay/Internals/Commands/Extensions.cs @@ -14,12 +14,12 @@ internal static IServiceCollection AddCommands( services.AddScoped(typeof(ICommandWithOperationResultExecutor<>).MakeGenericType(moduleType), typeof(CommandWithOperationResultExecutor<>).MakeGenericType(moduleType)); services.Scan(s => s.FromAssemblies(assemblies) - .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<,>))) - .AsImplementedInterfaces() - .WithScopedLifetime()); + .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<>))) + .AsImplementedInterfaces() + .WithScopedLifetime()); services.Scan(s => s.FromAssemblies(assemblies) - .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<>))) + .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<,>))) .AsImplementedInterfaces() .WithScopedLifetime()); diff --git a/source/EasyWay/Internals/Modules/ModuleExecutor.cs b/source/EasyWay/Internals/Modules/ModuleExecutor.cs index 047d36d..a3e1012 100644 --- a/source/EasyWay/Internals/Modules/ModuleExecutor.cs +++ b/source/EasyWay/Internals/Modules/ModuleExecutor.cs @@ -48,7 +48,8 @@ public async Task> Execute(Com return commandResult; } - public async Task> Execute(Query query, CancellationToken cancellationToken = default) + public async Task> Execute(TQuery query, CancellationToken cancellationToken = default) + where TQuery : Query where TReadModel : ReadModel { QueryResult result; @@ -59,7 +60,7 @@ public async Task> Execute(Query result = await sp .GetRequiredService>() - .Execute(query, cancellationToken); + .Execute(query, cancellationToken); } return result; diff --git a/source/EasyWay/Internals/Queries/IQueryExecutor.cs b/source/EasyWay/Internals/Queries/IQueryExecutor.cs index 0cc5b34..1cbf27c 100644 --- a/source/EasyWay/Internals/Queries/IQueryExecutor.cs +++ b/source/EasyWay/Internals/Queries/IQueryExecutor.cs @@ -3,7 +3,8 @@ internal interface IQueryExecutor where TModule : EasyWayModule { - Task> Execute(Query query, CancellationToken cancellationToken) + Task> Execute(TQuery query, CancellationToken cancellationToken = default) + where TQuery : Query where TReadModel : ReadModel; } } diff --git a/source/EasyWay/Internals/Queries/QueryExecutor.cs b/source/EasyWay/Internals/Queries/QueryExecutor.cs index 9dc89e8..86f295e 100644 --- a/source/EasyWay/Internals/Queries/QueryExecutor.cs +++ b/source/EasyWay/Internals/Queries/QueryExecutor.cs @@ -19,7 +19,8 @@ public QueryExecutor( _cancellationContextConstructor = cancellationContextConstructor; } - public async Task> Execute(Query query, CancellationToken cancellationToken) + public async Task> Execute(TQuery query, CancellationToken cancellationToken = default) + where TQuery : Query where TReadModel : ReadModel { _cancellationContextConstructor.Set(cancellationToken); @@ -28,13 +29,11 @@ public async Task> Execute(Query var validatorType = typeof(IEasyWayValidator<>).MakeGenericType(queryType); - var validator = _serviceProvider.GetService(validatorType); + var validator = _serviceProvider.GetService>(); if (validator is not null) { - var errors = (IDictionary)validatorType - .GetMethod("Validate") - ?.Invoke(validator, [query]); + var errors = validator.Validate(query); if (errors.Any()) { @@ -42,11 +41,9 @@ public async Task> Execute(Query } } - var queryHandlerType = typeof(IQueryHandler<,>).MakeGenericType( queryType, typeof(TReadModel)); + var queryHandler = _serviceProvider.GetRequiredService>(); - var queryHandler = _serviceProvider.GetRequiredService(queryHandlerType); - - var queryResult = await (Task>) queryHandlerType.GetMethod("Handle").Invoke(queryHandler, [query]); + var queryResult = await queryHandler.Handle(query); return queryResult; } From 21ef56b4faf0a13ce29945e56b654cdc30146cd5 Mon Sep 17 00:00:00 2001 From: adimiko Date: Sun, 9 Mar 2025 21:38:39 +0100 Subject: [PATCH 4/4] Changed command executor --- samples/EasyWay.Samples/Program.cs | 6 +++--- source/EasyWay/Command.cs | 2 +- source/EasyWay/IModuleExecutor.cs | 7 ++++--- .../CommandWithOperationResultExecutor.cs | 19 ++++++------------- .../EasyWay/Internals/Commands/Extensions.cs | 6 +++--- .../ICommandWithOperationResultExecutor.cs | 3 ++- .../Internals/Modules/ModuleExecutor.cs | 9 +++++---- 7 files changed, 24 insertions(+), 28 deletions(-) diff --git a/samples/EasyWay.Samples/Program.cs b/samples/EasyWay.Samples/Program.cs index c233009..568cd7c 100644 --- a/samples/EasyWay.Samples/Program.cs +++ b/samples/EasyWay.Samples/Program.cs @@ -33,19 +33,19 @@ await kernel app.MapPost("/query", async ([FromBody] SampleQuery query, IModuleExecutor executor, IWebApiResultMapper mapper) => { - var x = await executor.Execute(query); + var x = await executor.Query(query); return mapper.Map(x); }); app.MapPost("/command", async ([FromBody] SampleCommand command, IModuleExecutor executor, IWebApiResultMapper mapper) => { - return await executor.Execute(command); + return await executor.Command(command); }); app.MapPost("/commandwithresult", async ([FromBody] SampleCommandWithResult command, IModuleExecutor executor, IWebApiResultMapper mapper) => { - var x = await executor.Execute(command); + var x = await executor.Command(command); return mapper.Map(x); }); diff --git a/source/EasyWay/Command.cs b/source/EasyWay/Command.cs index 9a5240a..7ce2cb5 100644 --- a/source/EasyWay/Command.cs +++ b/source/EasyWay/Command.cs @@ -5,6 +5,6 @@ /// public abstract class Command; - public abstract class Command : Command + public abstract class Command where TCommandResult : OperationResult; } diff --git a/source/EasyWay/IModuleExecutor.cs b/source/EasyWay/IModuleExecutor.cs index 2031f7b..609093a 100644 --- a/source/EasyWay/IModuleExecutor.cs +++ b/source/EasyWay/IModuleExecutor.cs @@ -3,13 +3,14 @@ public interface IModuleExecutor where TModule : EasyWayModule { - Task Execute(TCommand command, CancellationToken cancellationToken = default) + Task Command(TCommand command, CancellationToken cancellationToken = default) where TCommand : Command; - Task> Execute(Command command, CancellationToken cancellationToken = default) + Task> Command(TCommand command, CancellationToken cancellationToken = default) + where TCommand : Command where TOperationResult : OperationResult; - Task> Execute(TQuery query, CancellationToken cancellationToken = default) + Task> Query(TQuery query, CancellationToken cancellationToken = default) where TQuery : Query where TReadModel : ReadModel; } diff --git a/source/EasyWay/Internals/Commands/CommandWithOperationResultExecutor.cs b/source/EasyWay/Internals/Commands/CommandWithOperationResultExecutor.cs index 7177cfd..1213a45 100644 --- a/source/EasyWay/Internals/Commands/CommandWithOperationResultExecutor.cs +++ b/source/EasyWay/Internals/Commands/CommandWithOperationResultExecutor.cs @@ -23,22 +23,17 @@ public CommandWithOperationResultExecutor( _unitOfWorkCommandHandler = unitOfWorkCommandHandler; } - public async Task> Execute(Command command, CancellationToken cancellationToken) + public async Task> Command(TCommand command, CancellationToken cancellationToken = default) + where TCommand : Command where TOperationResult : OperationResult { _cancellationContextConstructor.Set(cancellationToken); - var commandType = command.GetType(); - - var validatorType = typeof(IEasyWayValidator<>).MakeGenericType(commandType); - - var validator = _serviceProvider.GetService(validatorType); + var validator = _serviceProvider.GetService>(); if (validator is not null) { - var errors = (IDictionary)validatorType - .GetMethod("Validate") - ?.Invoke(validator, [command]); + var errors = validator.Validate(command); if (errors.Any()) { @@ -46,11 +41,9 @@ public async Task> Execute(Com } } - var commandHandlerType = typeof(ICommandHandler<,>).MakeGenericType(commandType, typeof(TOperationResult)); - - var commandHandler = _serviceProvider.GetRequiredService(commandHandlerType); + var commandHandler = _serviceProvider.GetRequiredService>(); - var commandResult = await (Task>)commandHandlerType.GetMethod("Handle").Invoke(commandHandler, [command]); + var commandResult = await commandHandler.Handle(command); await _unitOfWorkCommandHandler.Handle(); diff --git a/source/EasyWay/Internals/Commands/Extensions.cs b/source/EasyWay/Internals/Commands/Extensions.cs index 94aeb8a..eda3c67 100644 --- a/source/EasyWay/Internals/Commands/Extensions.cs +++ b/source/EasyWay/Internals/Commands/Extensions.cs @@ -14,9 +14,9 @@ internal static IServiceCollection AddCommands( services.AddScoped(typeof(ICommandWithOperationResultExecutor<>).MakeGenericType(moduleType), typeof(CommandWithOperationResultExecutor<>).MakeGenericType(moduleType)); services.Scan(s => s.FromAssemblies(assemblies) - .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<>))) - .AsImplementedInterfaces() - .WithScopedLifetime()); + .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<>))) + .AsImplementedInterfaces() + .WithScopedLifetime()); services.Scan(s => s.FromAssemblies(assemblies) .AddClasses(c => c.AssignableTo(typeof(ICommandHandler<,>))) diff --git a/source/EasyWay/Internals/Commands/ICommandWithOperationResultExecutor.cs b/source/EasyWay/Internals/Commands/ICommandWithOperationResultExecutor.cs index e1a0719..6388fb2 100644 --- a/source/EasyWay/Internals/Commands/ICommandWithOperationResultExecutor.cs +++ b/source/EasyWay/Internals/Commands/ICommandWithOperationResultExecutor.cs @@ -3,7 +3,8 @@ internal interface ICommandWithOperationResultExecutor where TModule : EasyWayModule { - Task> Execute(Command command, CancellationToken cancellationToken) + Task> Command(TCommand command, CancellationToken cancellationToken = default) + where TCommand : Command where TOperationResult : OperationResult; } } diff --git a/source/EasyWay/Internals/Modules/ModuleExecutor.cs b/source/EasyWay/Internals/Modules/ModuleExecutor.cs index a3e1012..de4af31 100644 --- a/source/EasyWay/Internals/Modules/ModuleExecutor.cs +++ b/source/EasyWay/Internals/Modules/ModuleExecutor.cs @@ -14,7 +14,7 @@ public ModuleExecutor(IServiceProvider serviceProvider) _serviceProvider = serviceProvider; } - public async Task Execute(TCommand command, CancellationToken cancellationToken = default) + public async Task Command(TCommand command, CancellationToken cancellationToken = default) where TCommand : Command { CommandResult commandResult; @@ -31,7 +31,8 @@ public async Task Execute(TCommand command, Cancellatio return commandResult; } - public async Task> Execute(Command command, CancellationToken cancellationToken = default) + public async Task> Command(TCommand command, CancellationToken cancellationToken = default) + where TCommand : Command where TOperationResult : OperationResult { CommandResult commandResult; @@ -42,13 +43,13 @@ public async Task> Execute(Com commandResult = await sp .GetRequiredService>() - .Execute(command, cancellationToken); + .Command(command, cancellationToken); } return commandResult; } - public async Task> Execute(TQuery query, CancellationToken cancellationToken = default) + public async Task> Query(TQuery query, CancellationToken cancellationToken = default) where TQuery : Query where TReadModel : ReadModel {