request/src/request.dispatcher/ScalarRequestInvoker.cs

47 lines
1.9 KiB
C#
Raw Normal View History

// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Geekeey.Request.Dispatcher;
internal abstract class ScalarRequestInvoker
{
public abstract Task<object?> HandleAsync(object request, IServiceProvider serviceProvider, CancellationToken cancellationToken);
}
internal abstract class ScalarRequestInvoker<TResponse> : ScalarRequestInvoker
{
public abstract Task<TResponse> HandleAsync(IScalarRequest<TResponse> request, IServiceProvider serviceProvider, CancellationToken cancellationToken);
}
internal sealed class ScalarRequestInvoker<TRequest, TResponse> : ScalarRequestInvoker<TResponse>
where TRequest : IScalarRequest<TResponse>
{
public override async Task<object?> HandleAsync(object request, IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
return await HandleAsync((IScalarRequest<TResponse>)request, serviceProvider, cancellationToken).ConfigureAwait(false);
}
public override Task<TResponse> HandleAsync(IScalarRequest<TResponse> request, IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
var options = serviceProvider.GetRequiredService<IOptions<RequestDispatcherOptions>>().Value;
var pipeline = options.GetRequestBehaviors<IScalarRequestBehavior<TRequest, TResponse>>(serviceProvider)
.Reverse()
.Aggregate((ScalarHandlerDelegate<TResponse>)Head, Chain);
return pipeline(request, cancellationToken);
static ScalarHandlerDelegate<TResponse> Chain(ScalarHandlerDelegate<TResponse> next, IScalarRequestBehavior<TRequest, TResponse> filter)
{
return (req, ct) => filter.HandleAsync((TRequest)req, next, ct);
}
Task<TResponse> Head(IScalarRequest<TResponse> r, CancellationToken ct)
{
return options.GetRequestHandlers<IScalarRequestHandler<TRequest, TResponse>>(serviceProvider).First().HandleAsync((TRequest)r, ct);
}
}
}