如何在Botframework V4中的每个对话框上访问存储而无需注入存储



您好,我试图将我的代码从去年1月的Bot Framework V4设计迁移到现在的新设计。在上一个代码中,我可以调用此代码:

var userstate = await (stepContext.Context.TurnState["BasicAccessors"] as BasicAccessors).BasicUserStateAccessor.GetAsync(stepContext.Context);

在每个对话框中以访问存储空间,但我不能做到,我需要每次依赖注入。如何在此新设计上实现此代码?谢谢。

    namespace BasicBot
    {
    public class BasicAccessors
    {
        public BasicAccessors(ConversationState conversationState, UserState userState)
        {
            ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState));
            UserState = userState ?? throw new ArgumentException(nameof(userState));
        }
        public static string DialogStateAccessorName { get; } = $"{nameof(BasicAccessors)}.DialogState";
        public static string BasicUserStateAccessorName { get; } = $"{nameof(BasicAccessors)}.BasicUserState";
        public IStatePropertyAccessor<BasicUserState> BasicUserStateAccessor { get; internal set; }
        public IStatePropertyAccessor<DialogState> DialogStateAccessor { get; internal set; }
        public ConversationState ConversationState { get; }
        public UserState UserState { get; }
    }
}

bot代码:

 public class DialogBot<T> : ActivityHandler where T : Dialog
{
    protected readonly Dialog Dialog;
    protected readonly BotState ConversationState;
    protected readonly BotState UserState;
    protected readonly ILogger Logger;
    public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger)
    {
        ConversationState = conversationState;
        UserState = userState;
        Dialog = dialog;
        Logger = logger;
    }
    public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        await base.OnTurnAsync(turnContext, cancellationToken);
        // Save any state changes that might have occured during the turn.
        var userStateAccessors = UserState.CreateProperty<BookingDetails>(nameof(BookingDetails));
        await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
    }
    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {
        Logger.LogInformation("Running dialog with Message Activity.");
        // Run the Dialog with the new message Activity.
        await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);
    }
}

启动:

  public class Startup
{
    public Startup()
    {
    }
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        // Create the credential provider to be used with the Bot Framework Adapter.
        services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();
        // Create the Bot Framework Adapter with error handling enabled.
        services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
        // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
        services.AddSingleton<IStorage, MemoryStorage>();
        // Create the User state. (Used in this bot's Dialog implementation.)
        services.AddSingleton<UserState>();
        // Create the Conversation state. (Used by the Dialog system itself.)
        services.AddSingleton<ConversationState>();
        services.AddSingleton<BasicAccessors>();
        // The Dialog that will be run by the bot.
        services.AddSingleton<MainDialog>();
        // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
        services.AddTransient<IBot, DialogBot<MainDialog>>();

    }
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }
        app.UseDefaultFiles();
        app.UseStaticFiles();
        //app.UseHttpsRedirection();
        app.UseMvc();
    }
}

}

我不知道您是否有解决方案,但是您不需要在每个对话框访问中进行依赖注入。您只需在启动中设置依赖项,在机器人中设置登录器,就可以根据需要访问属性。在此处查看文章和此处的示例。这在显示如何设置的工作中做出了不错的工作。

最新更新