private static ITaskMiddleware GetMiddleware( TaskMiddlewareDescriptor descriptor, IServiceProvider serviceProvider) { if (!s_factories.TryGetValue(descriptor, out Func <IServiceProvider, ITaskMiddleware> factory)) { if (descriptor.Func is object) { var middleware = new FuncMiddleware(descriptor.Func); factory = s_factories.GetOrAdd(descriptor, _ => middleware); return(middleware); } else if (serviceProvider.GetService(descriptor.Type) is ITaskMiddleware fetchedMiddleware) { s_factories[descriptor] = sp => (ITaskMiddleware)sp.GetRequiredService(descriptor.Type); return(fetchedMiddleware); } else { ObjectFactory objectFactory = ActivatorUtilities.CreateFactory( descriptor.Type, Array.Empty <Type>()); factory = s_factories.GetOrAdd( descriptor, sp => (ITaskMiddleware)objectFactory.Invoke(sp, Array.Empty <object>())); return(factory.Invoke(serviceProvider)); } } return(factory.Invoke(serviceProvider)); }
public async Task Run_Func_ExecutesTwice() { // arrange var next1 = new NextFunc(); var next2 = new NextFunc(); int executed = 0; Task Middleware(DispatchMiddlewareContext context, Func <Task> next) { executed++; return(next()); } var descriptor = new TaskMiddlewareDescriptor(Middleware); var context = CreateContext(); // act await TaskMiddlewareRunner.RunAsync(descriptor, context, next1.InvokeAsync); await TaskMiddlewareRunner.RunAsync(descriptor, context, next2.InvokeAsync); // assert executed.Should().Be(2); next1.ExecutionCount.Should().Be(1); next2.ExecutionCount.Should().Be(1); }
public async Task Run_Type_Executes(bool addMiddleware) { // arrange var next = new NextFunc(); var descriptor = TaskMiddlewareDescriptor.Create <TestMiddleware>(); IServiceProvider serviceProvider = CreateServiceProvider(addMiddleware); var context = CreateContext(serviceProvider); // act await TaskMiddlewareRunner.RunAsync(descriptor, context, next.InvokeAsync); // assert var tracker = serviceProvider.GetRequiredService <ExecutionTracker>(); tracker.ExecutionCount.Should().Be(1); next.ExecutionCount.Should().Be(1); }
/// <summary> /// Runs the middleware described by <see cref="TaskMiddlewareDescriptor"/>. /// </summary> /// <param name="descriptor">The task middleware to find and run.</param> /// <param name="context">The dispatch middleware context.</param> /// <param name="next">The next middleware callback.</param> /// <returns>A task that completes when the middleware has finished executing.</returns> public static Task RunAsync( TaskMiddlewareDescriptor descriptor, DispatchMiddlewareContext context, Func <Task> next) { Check.NotNull(descriptor, nameof(descriptor)); Check.NotNull(context, nameof(context)); Check.NotNull(next, nameof(next)); IServiceProvider serviceProvider = context.GetProperty <IServiceProvider>(); ITaskMiddleware middleware = GetMiddleware(descriptor, serviceProvider); if (middleware is null) { // This _should not_ be possible, as TaskMiddlewareDescriptor is designed to only be constructable with // valid values. But a good sanity check here. ILogger logger = serviceProvider.CreateLogger(typeof(TaskMiddlewareRunner)); string message = Strings.MiddlewareCreationFailed(descriptor); logger.LogError(message); throw new InvalidOperationException(message); // TODO: maybe a better exception type. } return(middleware.InvokeAsync(context, next)); }
public async Task Run_NullNext_Throws() { var descriptor = new TaskMiddlewareDescriptor((c, n) => Task.CompletedTask); Func <Task> act = () => TaskMiddlewareRunner.RunAsync(descriptor, CreateContext(), null); await act.Should().ThrowExactlyAsync <ArgumentNullException>(); }