首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用非静态触发器创建IFunctionProvider

使用非静态触发器创建IFunctionProvider
EN

Stack Overflow用户
提问于 2021-09-29 06:03:34
回答 1查看 238关注 0票数 2

我有一个Azure函数的IFunctionProvider实现,它为/healthcheck创建了一个路由。函数元数据的入口点是一个名为Somenamespace.TestTrigger.RenderHealthCheck的方法。我的代码如下所示:

代码语言:javascript
运行
复制
    public class TestTrigger
    {
        public static async Task<IActionResult> RenderHealthCheck(HttpRequest req)
        {
            return new OkObjectResult("OK");
        }        
    }
    
    public class HealthCheckTrigger : IFunctionProvider
    {
        public ImmutableDictionary<string, ImmutableArray<string>> FunctionErrors { get; }
        
        public async Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync()
        {
            var assembly = Assembly.GetExecutingAssembly();
            
            var functionMetadata = new FunctionMetadata()
            {
                Name = nameof(TestTrigger.RenderHealthCheck),
                FunctionDirectory = null,
                ScriptFile = $"assembly:{assembly.FullName}",
                EntryPoint = $"{typeof(TestTrigger).FullName}.{nameof(TestTrigger.RenderHealthCheck)}",
                Language = "DotNetAssembly"
            };

            var jo = JObject.FromObject(new HttpBindingMetadata()
            {
                Methods = new List<string> { HttpMethods.Get },
                Route = "HealthCheck",
                AuthLevel = AuthorizationLevel.Anonymous,
            });
            
            var binding = BindingMetadata.Create(jo);
            functionMetadata.Bindings.Add(binding);            
            
            var functionMetadataList = new List<FunctionMetadata>
            {
                functionMetadata
            };

            return await Task.FromResult(functionMetadataList.ToImmutableArray()).ConfigureAwait(false);
        }
    }

这很好,当我运行这个函数并命中/HealthCheck端点时,我会得到我的OK消息。但是,我想使RenderHealthCheck方法是非静态的,这样我就可以在构造函数中使用依赖项注入,并在我的应用程序中访问各种服务。我把我的代码改为:

代码语言:javascript
运行
复制
public class TestTrigger
{
    private readonly HealthCheckService healthCheckService;
    
    public TestTrigger(HealthCheckService healthCheckService)
    {
        this.healthCheckService = healthCheckService;
    }

    public async Task<IActionResult> RenderHealthCheck(HttpRequest req)
    {
        return new OkObjectResult("OK");
    }        
}

现在,当我到达端点时,会得到以下异常:

代码语言:javascript
运行
复制
Executed 'Functions.RenderHealthCheck' (Failed, Id=c02a9ba6-1ed3-4c07-8b38-214d345b6ff1, Duration=488ms)
Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: Functions.RenderHealthCheck
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at lambda_method(Closure , TestTrigger , Object[] )
   at Microsoft.Azure.WebJobs.Host.Executors.TaskMethodInvoker`2.InvokeAsync(TReflected instance, Object[] arguments) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\TaskMethodInvoker.cs:line 21
   at Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker.MethodInvoker`2.InvokeAsync(Object target, Object[] parameters) in D:\a\1\s\src\WebJobs.Script\Description\DotNet\DotNetFunctionInvoker.cs:line 533
   at Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker.InvokeCore(Object[] parameters, FunctionInvocationContext context) in D:\a\1\s\src\WebJobs.Script\Description\DotNet\DotNetFunctionInvoker.cs:line 272
   at Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase.Invoke(Object[] parameters) in D:\a\1\s\src\WebJobs.Script\Description\FunctionInvokerBase.cs:line 82
   at Microsoft.Azure.WebJobs.Script.Description.FunctionGenerator.Coerce[T](Task`1 src) in D:\a\1\s\src\WebJobs.Script\Description\FunctionGenerator.cs:line 225
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.InvokeAsync(Object instance, Object[] arguments) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 52
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeWithTimeoutAsync(IFunctionInvoker invoker, ParameterHelper parameterHelper, CancellationTokenSource timeoutTokenSource, CancellationTokenSource functionCancellationTokenSource, Boolean thro
wOnTimeout, TimeSpan timerInterval, IFunctionInstance instance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 555
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstanceEx instance, ParameterHelper parameterHelper, ILogger logger, CancellationTokenSource functionCancellationTokenSource) in C:\projects\azure-webjobs-sdk-r
qm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 503
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx instance, FunctionStartedMessage message, FunctionInstanceLogEntry instanceLogEntry, ParameterHelper parameterHelper, ILogger logger, CancellationToken
 cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 281
   --- End of inner exception stack trace --

我没有在FunctionMetadataHttpBindingMetadata中看到任何似乎控制入口点是否是静态的东西。实例方法根本不受支持吗?如果不是的话,似乎是一个巨大的限制。在IFunctionProvider上基本上没有任何类型的文档,所以不太确定从哪里开始。任何帮助都将不胜感激!

EN

Stack Overflow用户

发布于 2022-04-04 20:55:38

如果您确实希望能够将HealthCheckService注入静态函数,则可以为其创建自定义绑定并从FunctionExecutionContext解析服务。

基于https://microsoft.github.io/AzureTipsAndTricks/blog/tip247.html,我能够完成以下工作:

代码语言:javascript
运行
复制
[assembly: WebJobsStartup(typeof(HealthBindingStartup))]

[Binding]
[AttributeUsage(AttributeTargets.Parameter)]
public class HealthAttribute : Attribute
{
}

[Extension(nameof(HealthBinding))]
public class HealthBinding : IExtensionConfigProvider
{
    public void Initialize(ExtensionConfigContext context)
    {
        var rule = context.AddBindingRule<HealthAttribute>();
        rule.BindToInput((HealthAttribute attr, ValueBindingContext context) =>
        {
            var service = context.FunctionContext.CreateObjectInstance<HealthCheckService>();

            return Task.FromResult(service);
        });
    }
}

public static class HealthBindingExtension
{
    public static IWebJobsBuilder AddHealthBinding(this IWebJobsBuilder builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        builder.AddExtension<HealthBinding>();
        return builder;
    }
}

public class HealthBindingStartup : IWebJobsStartup
{
    public void Configure(IWebJobsBuilder builder)
    {
        builder.AddHealthBinding();
    }
}

这样,您就可以更新您的函数并添加[Health] HealthCheckService service,并让这个绑定注入您想要的服务。

此绑定的元数据是:

代码语言:javascript
运行
复制
{ "name": "service", "type": "health", "direction": "in" }

这是通过IFunctionProvider添加函数时所需要的,它忽略了任何属性。

票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69371155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档