Skip to content

Commit

Permalink
feat: ✨ migrate to use Mediator source generator instead of MediatR (#20
Browse files Browse the repository at this point in the history
)
  • Loading branch information
mehdihadeli authored Sep 24, 2024
1 parent a721911 commit e686950
Show file tree
Hide file tree
Showing 58 changed files with 426 additions and 400 deletions.
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ dotnet_diagnostic.CA1304.severity = error
# CA1307: Specify StringComparison for clarity
dotnet_diagnostic.CA1307.severity = error
# CA1308: Normalize strings to uppercase
dotnet_diagnostic.CA1308.severity = error
dotnet_diagnostic.CA1308.severity = none
# CA1309: Use ordinal StringComparison
dotnet_diagnostic.CA1309.severity = error
# CA1724: Type names should not match namespaces
Expand Down Expand Up @@ -236,7 +236,7 @@ dotnet_diagnostic.IDE0052.severity = error
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/csharp-formatting-options
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/dotnet-formatting-options
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0055
dotnet_diagnostic.IDE0055.severity = error
dotnet_diagnostic.IDE0055.severity = suggestion

# CS1574: XML comment on 'construct' has syntactically incorrect cref attribute 'name'
dotnet_diagnostic.CS1574.severity = error
Expand Down
8 changes: 4 additions & 4 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,15 @@ autolabeler:
title:
- '/^(feat)(\([a-z ]+\))?: .+/'
- label: 'minor'
branch:
branch:
- '/^(feat)(\([a-z ]+\))?\/.+/'
title:
title:
- '/^(feat)(\([a-z ]+\))?: .+/'
- label: 'patch'
branch:
branch:
- '/^(fix)(\([a-z ]+\))?\/.+/'
- '/^(ci)(\([a-z ]+\))?\/.+/'
title:
title:
- '/^(fix)(\([a-z ]+\))?: .+/'
- '/^(ci)(\([a-z ]+\))?: .+/'

Expand Down
142 changes: 75 additions & 67 deletions readme.md

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions src/App/Vertical.Slice.Template.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Scalar.AspNetCore;
using Serilog;
using Serilog.Events;
using Shared.Logging.Extensions;
Expand All @@ -8,9 +9,11 @@
using Vertical.Slice.Template.Shared.Extensions.WebApplicationBuilderExtensions;

// https://github.com/serilog/serilog-aspnetcore#two-stage-initialization
// https://github.com/serilog/serilog-extensions-hosting
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.WriteTo.Console()
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level} - {Message:lj}{NewLine}{Exception}")
.CreateBootstrapLogger();

try
Expand Down Expand Up @@ -87,9 +90,15 @@
{
// should register as last middleware for discovering all endpoints and its versions correctly
app.UseCustomSwagger();

// https://github.com/scalar/scalar/blob/main/packages/scalar.aspnetcore/README.md
app.MapScalarApiReference(x =>
{
x.OpenApiRoutePattern = "/swagger/v1/swagger.json";
});
}
// #endif

// #endif
await app.RunAsync();
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
<ItemGroup>
<ProjectReference Include="..\Vertical.Slice.Template\Vertical.Slice.Template.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using FluentValidation;
using MediatR;
using Microsoft.Extensions.Logging;
using Shared.Abstractions.Core.CQRS;
using Shared.Abstractions.Persistence.Ef;
Expand All @@ -19,7 +18,7 @@ namespace Vertical.Slice.Template.Products.Features.CreatingProduct.v1;
// https://codeopinion.com/leaking-value-objects-from-your-domain/
// https://www.youtube.com/watch?v=CdanF8PWJng
// we don't pass value-objects and domains to our commands and events, just primitive types
internal record CreateProduct(string Name, Guid CategoryId, decimal Price, string? Description = null)
public record CreateProduct(string Name, Guid CategoryId, decimal Price, string? Description = null)
: ICommand<CreateProductResult>
{
public Guid Id { get; } = IdGenerator.NewId();
Expand Down Expand Up @@ -55,7 +54,7 @@ internal class CreateProductHandler(
ILogger<CreateProductHandler> logger
) : ICommandHandler<CreateProduct, CreateProductResult>
{
public async Task<CreateProductResult> Handle(CreateProduct request, CancellationToken cancellationToken)
public async ValueTask<CreateProductResult> Handle(CreateProduct request, CancellationToken cancellationToken)
{
request.NotBeNull();

Expand All @@ -72,7 +71,7 @@ public async Task<CreateProductResult> Handle(CreateProduct request, Cancellatio
}
}

internal record CreateProductResult(Guid Id);
public record CreateProductResult(Guid Id);

internal class DbExecuters : IDbExecutors
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using Humanizer;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Shared.Abstractions.Web;
using Shared.Core.Extensions;
using Shared.Web.Minimal.Extensions;
using Shared.Web.ProblemDetail.HttpResults;

Expand Down Expand Up @@ -37,6 +37,8 @@ async Task<
{
var (request, context, mediator, cancellationToken) = requestParameters;

request.NotBeNull();

var command = request.ToCreateProduct();

var result = await mediator.Send(command, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Vertical.Slice.Template.Products.Features.CreatingProduct.v1;
// https://codeopinion.com/leaking-value-objects-from-your-domain/
// https://www.youtube.com/watch?v=CdanF8PWJng
// we don't pass value-objects and domains to our commands and events, just primitive types
internal record ProductCreated(Guid Id, string Name, Guid CategoryId, decimal Price, string? Description = null)
public record ProductCreated(Guid Id, string Name, Guid CategoryId, decimal Price, string? Description = null)
: DomainEvent
{
public static ProductCreated Of(Guid id, string? name, Guid categoryId, decimal price, string? description = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

namespace Vertical.Slice.Template.Products.Features.GettingProductById.v1;

internal record GetProductById(Guid Id) : CacheQuery<GetProductById, GetProductByIdResult>
public record GetProductById(Guid Id) : CacheQuery<GetProductById, GetProductByIdResult>
{
/// <summary>
/// GetProductById query with validation.
Expand Down Expand Up @@ -43,7 +43,7 @@ public GetProductByIdValidator()
internal class GetProductByIdHandler(DbExecutors.GetProductByIdExecutor getProductByIdExecutor)
: IQueryHandler<GetProductById, GetProductByIdResult>
{
public async Task<GetProductByIdResult> Handle(GetProductById request, CancellationToken cancellationToken)
public async ValueTask<GetProductByIdResult> Handle(GetProductById request, CancellationToken cancellationToken)
{
request.NotBeNull();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Humanizer;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

namespace Vertical.Slice.Template.Products.Features.GettingProductsByPage.v1;

internal record GetProductsByPage : PageQuery<GetProductsByPageResult>
public record GetProductsByPage : PageQuery<GetProductsByPageResult>
{
/// <summary>
/// GetProductById query with validation.
Expand Down Expand Up @@ -56,7 +56,10 @@ internal class GetProductByPageHandler(
ISieveProcessor sieveProcessor
) : IQueryHandler<GetProductsByPage, GetProductsByPageResult>
{
public async Task<GetProductsByPageResult> Handle(GetProductsByPage request, CancellationToken cancellationToken)
public async ValueTask<GetProductsByPageResult> Handle(
GetProductsByPage request,
CancellationToken cancellationToken
)
{
request.NotBeNull();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Humanizer;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using CorrelationId.DependencyInjection;
using MediatR;
using Mediator;
using Microsoft.AspNetCore.Builder;
using Shared.Abstractions.Persistence.Ef.Repository;
using Shared.Cache;
Expand Down Expand Up @@ -47,7 +47,13 @@ public static WebApplicationBuilder AddInfrastructures(this WebApplicationBuilde

builder.Services.AddHttpContextAccessor();

builder.Services.AddMediatR(c => c.RegisterServicesFromAssembly(typeof(CatalogsMetadata).Assembly));
// https://github.com/martinothamar/Mediator
builder.Services.AddMediator(options =>
{
options.ServiceLifetime = ServiceLifetime.Transient;
options.Namespace = "Vertical.Slice.Template";
});

builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(StreamLoggingBehavior<,>));
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestValidationBehavior<,>));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Vertical.Slice.Template.Shared.Extensions.WebApplicationExtensions;

public static partial class WebApplicationExtensions
{
public static Task UseInfrastructure(this WebApplication app)
public static async Task UseInfrastructure(this WebApplication app)
{
app.UseCustomCors();

Expand All @@ -17,6 +17,6 @@ public static Task UseInfrastructure(this WebApplication app)
// https://github.com/stevejgordon/CorrelationId
app.UseCorrelationId();

return Task.CompletedTask;
await app.MigrateDatabases();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Builder;
using Shared.Abstractions.Persistence;

namespace Vertical.Slice.Template.Shared.Extensions.WebApplicationExtensions;

public static partial class WebApplicationExtensions
{
public static async Task MigrateDatabases(this WebApplication app)
{
using var scope = app.Services.CreateScope();
var migrationManager = scope.ServiceProvider.GetRequiredService<IMigrationManager>();

await migrationManager.ExecuteAsync(CancellationToken.None);
}
}
4 changes: 2 additions & 2 deletions src/App/Vertical.Slice.Template/Users/GetUsers/GetUsers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Vertical.Slice.Template.Users.GetUsers;

internal record GetUsersByPage : PageQuery<GetUsersByPageResult>
public record GetUsersByPage : PageQuery<GetUsersByPageResult>
{
/// <summary>
/// GetUsersByPage query with validation.
Expand All @@ -29,7 +29,7 @@ public static GetUsersByPage Of(PageRequest pageRequest)

internal class GetUsersHandler(IUsersHttpClient usersHttpClient) : IQueryHandler<GetUsersByPage, GetUsersByPageResult>
{
public async Task<GetUsersByPageResult> Handle(GetUsersByPage request, CancellationToken cancellationToken)
public async ValueTask<GetUsersByPageResult> Handle(GetUsersByPage request, CancellationToken cancellationToken)
{
var usersList = await usersHttpClient.GetAllUsersAsync(request, cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Humanizer;
using MediatR;
using Mediator;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
Expand Down
1 change: 1 addition & 0 deletions src/App/Vertical.Slice.Template/Usings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using IMediator = Mediator.IMediator;
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,12 @@
<InternalsVisibleTo Include="Vertical.Slice.Template.UnitTests" />
<InternalsVisibleTo Include="Vertical.Slice.Template.TestsShared" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Mediator.SourceGenerator">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
8 changes: 4 additions & 4 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<PackageVersion Include="Ben.Demystifier" Version="0.4.1" />
<PackageVersion Include="EventStore.Client.Grpc.Streams" Version="23.3.3" />
<PackageVersion Include="Marten" Version="7.24.0" />
<PackageVersion Include="Mediator.Abstractions" Version="2.1.7" />
<PackageVersion Include="Mediator.SourceGenerator" Version="2.1.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
Expand Down Expand Up @@ -55,6 +57,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.7" />
<PackageVersion Include="Open.ChannelExtensions" Version="8.4.3" />
<PackageVersion Include="Riok.Mapperly" Version="3.6.0" />
<PackageVersion Include="Scalar.AspNetCore" Version="1.2.4" />
<PackageVersion Include="Serilog.Exceptions.EntityFrameworkCore" Version="8.4.0" />
<PackageVersion Include="Serilog.Sinks.Grafana.Loki" Version="8.3.0" />
<PackageVersion Include="Serilog.Sinks.OpenTelemetry" Version="4.1.0-dev-00336" />
Expand Down Expand Up @@ -148,9 +151,6 @@
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.8" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="MediatR" Version="12.4.0" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="Bogus" Version="35.5.1" />
<PackageVersion Include="AutoBogus" Version="2.13.1" />
Expand Down Expand Up @@ -207,4 +207,4 @@
<ItemGroup>
<PackageVersion Include="NSubstitute" Version="5.1.0" />
</ItemGroup>
</Project>
</Project>
2 changes: 1 addition & 1 deletion src/Shared/Abstractions/Caching/ICacheRequest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MediatR;
using Mediator;

namespace Shared.Abstractions.Caching;

Expand Down
2 changes: 1 addition & 1 deletion src/Shared/Abstractions/Caching/IInvalidateCacheRequest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MediatR;
using Mediator;

namespace Shared.Abstractions.Caching;

Expand Down
4 changes: 2 additions & 2 deletions src/Shared/Abstractions/Core/CQRS/ICommand.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using MediatR;
using Mediator;

namespace Shared.Abstractions.Core.CQRS;

public interface ICommand : IRequest;

public interface ICommand<out TResponse> : IRequest<TResponse>
public interface ICommand<TResponse> : IRequest<TResponse>
where TResponse : class;
2 changes: 1 addition & 1 deletion src/Shared/Abstractions/Core/CQRS/ICommandHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MediatR;
using Mediator;

namespace Shared.Abstractions.Core.CQRS;

Expand Down
3 changes: 1 addition & 2 deletions src/Shared/Abstractions/Core/CQRS/IQuery.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using MediatR;
using Mediator;

namespace Shared.Abstractions.Core.CQRS;

public interface IQuery<out TResponse> : IRequest<TResponse>
where TResponse : class;

// https://jimmybogard.com/mediatr-10-0-released/
public interface IStreamQuery<out T> : IStreamRequest<T>
where T : notnull;
3 changes: 1 addition & 2 deletions src/Shared/Abstractions/Core/CQRS/IQueryHandler.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using MediatR;
using Mediator;

namespace Shared.Abstractions.Core.CQRS;

public interface IQueryHandler<in TQuery, TResponse> : IRequestHandler<TQuery, TResponse>
where TQuery : IQuery<TResponse>
where TResponse : class;

// https://jimmybogard.com/mediatr-10-0-released/
public interface IStreamQueryHandler<in TQuery, out TResponse> : IStreamRequestHandler<TQuery, TResponse>
where TQuery : IStreamQuery<TResponse>
where TResponse : class;
2 changes: 1 addition & 1 deletion src/Shared/Abstractions/Core/Domain/Events/IEvent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MediatR;
using Mediator;

namespace Shared.Abstractions.Core.Domain.Events;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MediatR;
using Mediator;

namespace Shared.Abstractions.Core.Domain.Events;

Expand Down
2 changes: 1 addition & 1 deletion src/Shared/Abstractions/Web/IHttpCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MediatR;
using Mediator;
using Microsoft.AspNetCore.Http;

namespace Shared.Abstractions.Web;
Expand Down
Loading

0 comments on commit e686950

Please sign in to comment.