src/DotNetWorker.Core/Invocation/DefaultFunctionExecutor.cs (43 lines of code) (raw):

// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; using System.Collections.Concurrent; using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Extensions.Logging; namespace Microsoft.Azure.Functions.Worker.Invocation { internal partial class DefaultFunctionExecutor : IFunctionExecutor { private readonly ConcurrentDictionary<string, IFunctionInvoker> _invokerCache = new(); private readonly ILogger<DefaultFunctionExecutor> _logger; private readonly IFunctionInvokerFactory _invokerFactory; public DefaultFunctionExecutor(IFunctionInvokerFactory invokerFactory, ILogger<DefaultFunctionExecutor> logger) { _invokerFactory = invokerFactory ?? throw new ArgumentNullException(nameof(invokerFactory)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } public async ValueTask ExecuteAsync(FunctionContext context) { var invoker = _invokerCache.GetOrAdd(context.FunctionId, static (_, state) => { var (factory, context) = state; return factory.Create(context.FunctionDefinition); }, (_invokerFactory, context)); object? instance = invoker.CreateInstance(context); var inputBindingFeature = context.Features.Get<IFunctionInputBindingFeature>(); FunctionInputBindingResult inputBindingResult; if (inputBindingFeature is null) { Log.FunctionInputFeatureUnavailable(_logger, context); var emptyArgsArray = new object?[context.FunctionDefinition.Parameters.Length]; inputBindingResult = new(emptyArgsArray); } else { inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); } context.GetBindings().InvocationResult = await invoker.InvokeAsync(instance, inputBindingResult.Values); } } }