Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 1 addition & 6 deletions docs/Registering and Calling Handlers.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,5 @@ public Task<Result> ExecuteAsync(string property, CancellationToken cancellation

## Directly

Simply expose the base `ExecuteAsync` method with a new public method, passing in a command/query request object directly.
Simply call the base `ExecuteAsync` method, passing in a command/query request object directly.

```csharp
// Inside DoThingHandler
public new Task<Result> ExecuteAsync(DoThingCommand command, CancellationToken cancellationToken = default)
=> base.ExecuteAsync(command, cancellationToken);
```
6 changes: 2 additions & 4 deletions src/DannyGoodacre.Core/CommandQuery/CommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ public abstract class CommandHandler<TCommand>(ILogger logger)
: CommandHandlerBase<TCommand, Result>(logger)
where TCommand : ICommand
{
protected private override Result MapResult(Result result)
=> result;
protected private override Result MapResult(Result result) => result;
}

/// <summary>
Expand All @@ -28,6 +27,5 @@ public abstract class CommandHandler<TCommand, TResult>(ILogger logger)
: CommandHandlerBase<TCommand, Result<TResult>>(logger)
where TCommand : ICommand
{
protected private override Result<TResult> MapResult(Result result)
=> new(result);
protected private override Result<TResult> MapResult(Result result) => new(result);
}
5 changes: 3 additions & 2 deletions src/DannyGoodacre.Core/CommandQuery/CommandHandlerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ protected virtual void Validate(ValidationState validationState, TCommand comman
/// <param name="command">The command to validate and process.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while performing the operation.</param>
/// <returns>A <see cref="Result"/> indicating the outcome of the operation.</returns>
protected async Task<TResult> ExecuteAsync(TCommand command, CancellationToken cancellationToken = default)
// ReSharper disable once MemberCanBeProtected.Global
public async virtual Task<TResult> ExecuteAsync(TCommand command, CancellationToken cancellationToken = default)
{
var validationState = new ValidationState();

Expand Down Expand Up @@ -76,7 +77,7 @@ protected async Task<TResult> ExecuteAsync(TCommand command, CancellationToken c
}
catch (Exception ex)
{
// LogFailed(Logger, ex, CommandName);
LogFailed(Logger, ex, CommandName);

return MapResult(Result.InternalError(ex.Message));
}
Expand Down
7 changes: 3 additions & 4 deletions src/DannyGoodacre.Core/CommandQuery/QueryHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ public abstract partial class QueryHandler<TQuery, TResult>(ILogger logger)
/// </summary>
/// <param name="validationState">A <see cref="ValidationState"/> to populate with the operation's outcome.</param>
/// <param name="queryRequest">The query request to validate.</param>
protected virtual void Validate(ValidationState validationState, TQuery queryRequest)
{
}
protected virtual void Validate(ValidationState validationState, TQuery queryRequest) { }

/// <summary>
/// The internal query logic.
Expand All @@ -34,7 +32,8 @@ protected virtual void Validate(ValidationState validationState, TQuery queryReq
/// <param name="query">The query to validate and process.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while performing the operation.</param>
/// <returns>A <see cref="Result{T}"/> indicating the outcome of the operation.</returns>
protected async Task<Result<TResult>> ExecuteAsync(TQuery query, CancellationToken cancellationToken)
// ReSharper disable once MemberCanBeProtected.Global
public async Task<Result<TResult>> ExecuteAsync(TQuery query, CancellationToken cancellationToken = default)
{
var validationState = new ValidationState();

Expand Down
6 changes: 2 additions & 4 deletions src/DannyGoodacre.Core/CommandQuery/StateCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ public abstract class StateCommandHandler<TCommand>(ILogger logger, IStateUnit s
: StateCommandHandlerBase<TCommand, Result>(logger, stateUnit)
where TCommand : ICommand
{
protected private override Result MapResult(Result result)
=> result;
protected private override Result MapResult(Result result) => result;
}

/// <summary>
Expand All @@ -28,6 +27,5 @@ public abstract class StateCommandHandler<TCommand, TResult>(ILogger logger, ISt
: StateCommandHandlerBase<TCommand, Result<TResult>>(logger, stateUnit)
where TCommand : ICommand
{
protected private override Result<TResult> MapResult(Result result)
=> new(result);
protected private override Result<TResult> MapResult(Result result) => new(result);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ internal StateCommandHandlerBase(ILogger logger, IStateUnit stateUnit) : base(lo

private IStateUnit StateUnit { get; }

protected new async Task<TResult> ExecuteAsync(TCommand command, CancellationToken cancellationToken = default)
public async override Task<TResult> ExecuteAsync(TCommand command, CancellationToken cancellationToken = default)
{
try
{
var result = await base.ExecuteAsync(command, cancellationToken);
TResult result = await base.ExecuteAsync(command, cancellationToken);

if (result.IsSuccess)
{
await StateUnit.SaveChangesAsync(cancellationToken);
_ = await StateUnit.SaveChangesAsync(cancellationToken);
}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ public abstract class TransactionCommandHandler<TCommand>(ILogger logger, ITrans
: TransactionCommandHandlerBase<TCommand, Result>(logger, transactionUnit)
where TCommand : ICommand
{
protected private override Result MapResult(Result result)
=> result;
protected private override Result MapResult(Result result) => result;
}

/// <summary>
Expand All @@ -30,6 +29,5 @@ public abstract class TransactionCommandHandler<TCommand, TResult>(ILogger logge
: TransactionCommandHandlerBase<TCommand, Result<TResult>>(logger, transactionUnit)
where TCommand : ICommand
{
protected private override Result<TResult> MapResult(Result result)
=> new(result);
protected private override Result<TResult> MapResult(Result result) => new(result);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ internal TransactionCommandHandlerBase(ILogger logger, ITransactionUnit transact
/// </remarks>
protected virtual int ExpectedChanges { get; set; } = -1;

protected new async Task<TResult> ExecuteAsync(TCommand command, CancellationToken cancellationToken)
public async override Task<TResult> ExecuteAsync(TCommand command, CancellationToken cancellationToken = default)
{
await using var transaction = await TransactionUnit.BeginTransactionAsync(cancellationToken);
await using ITransaction transaction = await TransactionUnit.BeginTransactionAsync(cancellationToken);

try
{
var result = await base.ExecuteAsync(command, cancellationToken);
TResult result = await base.ExecuteAsync(command, cancellationToken);

if (!result.IsSuccess)
{
Expand All @@ -42,7 +42,7 @@ internal TransactionCommandHandlerBase(ILogger logger, ITransactionUnit transact
return result;
}

var actualChanges = await TransactionUnit.SaveChangesAsync(cancellationToken);
int actualChanges = await TransactionUnit.SaveChangesAsync(cancellationToken);

if (ExpectedChanges != -1 && actualChanges != ExpectedChanges)
{
Expand Down
4 changes: 2 additions & 2 deletions src/DannyGoodacre.Core/DannyGoodacre.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<PackageId>DannyGoodacre.Core</PackageId>
<Version>0.4.0</Version>
<Version>0.5.0</Version>
<Authors>Danny Goodacre</Authors>
<Description>A lightweight CQRS and clean architecture foundation library, including a result pattern and state management.</Description>
<RepositoryUrl>https://github.com/dannygoodacre/DannyGoodacre.Core</RepositoryUrl>
Expand All @@ -13,7 +13,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.6" />
</ItemGroup>

<ItemGroup>
Expand Down
18 changes: 9 additions & 9 deletions src/DannyGoodacre.Core/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ public static class ServiceCollectionExtensions
{
public IServiceCollection AddCommandHandlers(params Assembly[] assemblies)
{
var handlerTypes = assemblies
IEnumerable<Type> handlerTypes = assemblies
.SelectMany(x => x.GetTypes())
.Where(x => x is { IsAbstract: false, IsClass: true } && x.IsCommandHandler());

foreach (var handlerType in handlerTypes)
foreach (Type handlerType in handlerTypes)
{
services.AddScoped(handlerType);
_ = services.AddScoped(handlerType);

var interfaces = handlerType.GetHandlerInterfaces();
IEnumerable<Type> interfaces = handlerType.GetHandlerInterfaces();

foreach (var serviceType in interfaces)
foreach (Type serviceType in interfaces)
{
services.AddScoped(serviceType, handlerType);
}
Expand All @@ -32,17 +32,17 @@ public IServiceCollection AddCommandHandlers(params Assembly[] assemblies)

public IServiceCollection AddQueryHandlers(params Assembly[] assemblies)
{
var handlerTypes = assemblies
IEnumerable<Type> handlerTypes = assemblies
.SelectMany(x => x.GetTypes())
.Where(x => x is { IsAbstract: false, IsClass: true } && x.IsQueryHandler());

foreach (var handlerType in handlerTypes)
foreach (Type handlerType in handlerTypes)
{
services.AddScoped(handlerType);

var interfaces = handlerType.GetHandlerInterfaces();
IEnumerable<Type> interfaces = handlerType.GetHandlerInterfaces();

foreach (var serviceType in interfaces)
foreach (Type serviceType in interfaces)
{
services.AddScoped(serviceType, handlerType);
}
Expand Down
8 changes: 4 additions & 4 deletions src/DannyGoodacre.Core/Extensions/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ internal static class TypeExtensions
{
public bool IsCommandHandler()
{
var baseType = type.BaseType;
Type? baseType = type.BaseType;

while (baseType is not null)
{
if (baseType.IsGenericType)
{
var definition = baseType.GetGenericTypeDefinition();
Type definition = baseType.GetGenericTypeDefinition();

if (definition == typeof(CommandHandlerBase<,>))
{
Expand All @@ -30,13 +30,13 @@ public bool IsCommandHandler()

public bool IsQueryHandler()
{
var baseType = type.BaseType;
Type? baseType = type.BaseType;

while (baseType is not null)
{
if (baseType.IsGenericType)
{
var definition = baseType.GetGenericTypeDefinition();
Type definition = baseType.GetGenericTypeDefinition();

if (definition == typeof(QueryHandler<,>))
{
Expand Down
2 changes: 1 addition & 1 deletion src/DannyGoodacre.Core/ValidationState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public IReadOnlyDictionary<string, IEnumerable<string>> Errors

public void AddError(string property, string error)
{
if (_errors.TryGetValue(property, out var err))
if (_errors.TryGetValue(property, out List<string>? err))
{
err.Add(error);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<PackageId>DannyGoodacre.Testing.Core</PackageId>
<Version>0.3.0</Version>
<Version>0.5.0</Version>
<Authors>Danny Goodacre</Authors>
<Description>A lightweight testing foundation library.</Description>
<RepositoryUrl>https://github.com/dannygoodacre/DannyGoodacre.Core</RepositoryUrl>
Expand All @@ -13,10 +13,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.6" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.6" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="NUnit" Version="4.4.0" />
<PackageReference Include="NUnit" Version="4.5.1" />
</ItemGroup>

<ItemGroup>
Expand Down
6 changes: 2 additions & 4 deletions src/DannyGoodacre.Testing.Core/StateCommandHandlerTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@ public void StateSetUp()
protected Mock<IStateUnit> StateUnitMock { get; private set; } = null!;

protected void SetupLogger_CanceledWhilePersistingChanges()
=> LoggerMock.Setup(LogLevel.Information,
$"Command '{CommandName}' was canceled while persisting changes.");
=> LoggerMock.Setup(LogLevel.Information, $"Command '{CommandName}' was canceled while persisting changes.");

protected void SetupLogger_FailedWhilePersistingChanges(Exception exception)
=> LoggerMock.Setup(LogLevel.Critical,
$"Command '{CommandName}' failed while persisting changes.", exception: exception);
=> LoggerMock.Setup(LogLevel.Critical, $"Command '{CommandName}' failed while persisting changes.", exception: exception);

protected void SetupStateUnit_SaveChangesAsync()
=> StateUnitMock
Expand Down
19 changes: 9 additions & 10 deletions src/DannyGoodacre.Testing.Core/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ namespace DannyGoodacre.Testing.Core;
public abstract class TestBase
{
[TearDown]
public void BaseTearDown()
=> VerifyAllAndNoOtherCalls();
public void BaseTearDown() => VerifyAllAndNoOtherCalls();

protected static void AssertSuccess(Result result)
{
Expand Down Expand Up @@ -132,26 +131,26 @@ protected static void AssertInternalError<T>(Result<T> result, string error)

private void VerifyAllAndNoOtherCalls()
{
var mockFields = GetType()
IEnumerable<FieldInfo> mockFields = GetType()
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => f.FieldType.IsGenericType
&& f.FieldType.GetGenericTypeDefinition() == typeof(Mock<>));
.Where(x => x.FieldType.IsGenericType
&& x.FieldType.GetGenericTypeDefinition() == typeof(Mock<>));

foreach (var mockField in mockFields)
foreach (FieldInfo mockField in mockFields)
{
var mock = mockField.GetValue(this);
object? mock = mockField.GetValue(this);

if (mock is null)
{
continue;
}

var type = mock.GetType();
Type type = mock.GetType();

var verifyAllMethod = type.GetMethod("VerifyAll", Type.EmptyTypes);
MethodInfo? verifyAllMethod = type.GetMethod("VerifyAll", Type.EmptyTypes);
verifyAllMethod?.Invoke(mock, null);

var verifyNoOtherCallsMethod = type.GetMethod("VerifyNoOtherCalls", Type.EmptyTypes);
MethodInfo? verifyNoOtherCallsMethod = type.GetMethod("VerifyNoOtherCalls", Type.EmptyTypes);
verifyNoOtherCallsMethod?.Invoke(mock, null);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ public override void BaseSetUp()

protected void SetupLogger_UnexpectedNumberOfChanges(int expected, int actual)
=> LoggerMock
.Setup(LogLevel.Error,
$"Command '{CommandName}' attempted to persist an unexpected number of changes: Expected '{expected}', Actual '{actual}'.");
.Setup(LogLevel.Error, $"Command '{CommandName}' attempted to persist an unexpected number of changes: Expected '{expected}', Actual '{actual}'.");

protected void SetupLogger_CanceledDuringRollback()
=> LoggerMock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="NUnit" Version="4.4.0" />
<PackageReference Include="NUnit" Version="4.5.1" />
<PackageReference Include="NUnit3TestAdapter" Version="6.0.1" />
</ItemGroup>

Expand Down
Loading