繁体   English   中英

Azure聊天机器人中间件的依赖注入?

[英]Dependency Injection for Azure chat bot middleware?

我正在使用Azure Bot Service和QnAMaker开发新的聊天机器人。 我们正在使用BotBuilder中间件(包括自定义中间件)来调整bot行为。

其中一种中间件将调用Azure函数,我想将新的HttpClientFactory功能与自定义中间件一起使用-但这需要依赖项注入。

如何像在常规.NET Core中间件中一样在BotBuilder中间件中使用依赖项注入?

当您查看Startup.cs中的bot配置时,您会看到它如何要求您更新所有bot依赖项:

services.AddHttpClient<MyFunctionClient>(client =>
{
    client.BaseAddress = new Uri(mySettings.GetValue<string>("myFunctionUrl"));
    client.DefaultRequestHeaders.Add("x-functions-key", mySettings.GetValue<string>("myFunctionKey"));
});

services.AddBot<QnAMakerBot>(options =>
{  
    options.CredentialProvider = new ConfigurationCredentialProvider(Configuration);

    options.ConnectorClientRetryPolicy = new RetryPolicy(
        new BotFrameworkHttpStatusCodeErrorDetectionStrategy(),
        3,
        TimeSpan.FromSeconds(2), 
        TimeSpan.FromSeconds(20),
        TimeSpan.FromSeconds(1));

    var middleware = options.Middleware;
    middleware.Add(new ConversationState<ChatLog>(new MemoryStorage()));
    middleware.Add(new MyCustomMiddleware()); // <- I want to inject a typed HttpClient here

//... etc. ....

有没有其他方法可以配置允许依赖项注入的机器人?

如果MyCustomMiddleware在其构造函数中需要一个类型化的HttpClient ,则必须在此处创建一个新实例,这样我就无法从DI和刚刚设置的配置中受益。

虽然我不喜欢服务定位器模式,但是Bot配置的当前设计不是非常依赖于依赖注入。

利用机器人中间件设置方式的本质,但必须在启动过程中提供一个新实例,我提出了以下解决方案。

public class BotMiddlewareAdapter<TMiddleware> : IMiddleware
    where TMiddleware : IMiddleware {
    private readonly Lazy<TMiddleware> middleware;

    public BotMiddlewareAdapter(IServiceCollection services) {
        middleware = new Lazy<TMiddleware>(() =>
            services.BuildServiceProvider().GetRequiredService<TMiddleware>());
    }

    public Task OnTurn(ITurnContext context, MiddlewareSet.NextDelegate next) {
        return middleware.Value.OnTurn(context, next);
    }
}

它以IServiceCollection作为显式依赖项,并延迟了服务提供者的创建以及工厂委托中最终中间件的最终解析。

然后可以使用

middleware.Add(new BotMiddlewareAdapter<MyCustomMiddleware>(services));

调用适配器时,它将在初始调用时延迟解析预期的中间件,然后调用它。

实际上,您可以再进一步一步,并将其转换为扩展方法

public static class BotBuilderMiddlewareExtension {
    public static void Add<TMiddleware>(this IList<IMiddleware> middleware, IServiceCollection services) 
        where TMiddleware : IMiddleware {
        middleware.Add(new BotMiddlewareAdapter<TMiddleware>(services));
    }
}

这简化了设置

middleware.Add<MyCustomMiddleware>(services);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM