如何在Botframework V4中的每个对话框上不依赖注入地访问存储

时间:2019-07-08 12:52:09

标签: c# botframework

您好,我正在尝试将代码从去年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; }
    }
}

机器人代码:

 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();
    }
}

}

1 个答案:

答案 0 :(得分:0)

我不知道您是否有解决方案,但是您不需要对每个对话框访问都进行依赖注入。您只需在启动时设置依赖项,在bot中设置访问器,然后就可以根据需要访问属性。看一下article heresample here。这样可以很好地说明应如何设置它们。