49 lines
1.9 KiB
C#
49 lines
1.9 KiB
C#
// Copyright (c) The Geekeey Authors
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
using System.Diagnostics;
|
|
|
|
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 [StackTraceHidden] (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);
|
|
}
|
|
}
|
|
}
|