在不将UserState注入每个对话框的情况下访问模型/数据库 [英] Accessing model/database without injecting the UserState to every dialog

查看:75
本文介绍了在不将UserState注入每个对话框的情况下访问模型/数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从旧的botframework v4迁移到最新版本.我大约有50个对话框类,要在所有这些对话框上注入用户状态依赖关系,需要做很多工作.

I am migrating from the old botframework v4 to the latest version. I have around 50 dialog classes and it is so much work to inject the userstate dependency on all of them.

在我可以通过以下代码访问模型之前:

Before i can access the model by just this code:

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

,无需在每个对话框中插入userState.我尝试这样做,但出现500个错误和其他错误.如何将这种方法复制到最新版本?

and no need to inject the userState in every dialog. I tried doing this but got 500 error and other ones. How can i replicate this method to the latest version?

这是旧版本中的代码.

BasicAccessors类:

BasicAccessors class:

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

OnTurnAsync:

OnTurnAsync:

          turnContext.TurnState.Add("BasicAccessors", _basicAccessors);

启动:

           services.AddSingleton<BasicAccessors>(sp =>
        {
            var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;

            var conversationState = options.State.OfType<ConversationState>().FirstOrDefault();

            var userState = options.State.OfType<UserState>().FirstOrDefault();

            var accessors = new BasicAccessors(conversationState, userState)
            {
                DialogStateAccessor = conversationState.CreateProperty<DialogState>(BasicAccessors.DialogStateAccessorName),
                BasicUserStateAccessor = userState.CreateProperty<BasicUserState>(BasicAccessors.BasicUserStateAccessorName),
            };

            return accessors;
        });

推荐答案

我实际上只是您已经具有-accessors类.您只需要将其更改为类似以下内容(调整以匹配您的代码)即可:

You already have an -accessors class. You just need to change it to something more like this (adjust to match your code):

using Microsoft.Bot.Builder;
using Microsoft.BotBuilderSamples;

namespace Microsoft.BotBuilderSamples
{
    public class BasicAccessors
    {
        public IStatePropertyAccessor<ConversationData> ConversationStateAccessors { get; }
        public IStatePropertyAccessor<UserProfile> UserStateAccessors { get; }

        public StateAccessors(ConversationState conversationState, UserState userState)
        {
            ConversationStateAccessors = conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
            UserStateAccessors = userState.CreateProperty<UserProfile>(nameof(UserProfile));
        }
    }
}

注意如何分别通过*State.CreateProperty<*>(nameof(*));

然后,在Startup.cs中,您只需要:

Then, in Startup.cs, you just need:

services.AddSingleton<StateAccessors>();
services.AddSingleton<MyDialogThatNeedsAccessors>(); // Call this for each of your Dialogs

然后,在需要访问器的对话框中,

Then, in your dialogs that need the accessors,

public MyDialogThatNeedsAccessors(BasicAccessors stateAccessors)
{
    _userProfileAccessor = stateAccessors.UserStateAccessors;
}

然后,要在对话框中访问它,您只需执行以下操作:

Then, to access it within your dialog, you just do something like:

var userProfile = await _userProfileAccessor.GetAsync(stepContext.Context, () => new UserProfile());

对于不需要访问器的对话框,只需将其保留在构造函数之外即可.

For dialogs that don't need the accessors, just leave it out of the constructor.

这篇关于在不将UserState注入每个对话框的情况下访问模型/数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆