c# - 如何将 DbContext(或任何其他对象)注入(inject)对话框?

标签 c# autofac botframework

假设我想在这个例子中将订单保存到数据库 PizzaOrderDialog.cs

我可以将 DbConext 注入(inject) Controller ,例如这个https://github.com/Microsoft/BotBuilder/blob/master/CSharp/Samples/PizzaBot/Controllers/MessagesController.cs但如何在 PizzaOrderDialog.cs 中使用它

我不能只将 DbContext 作为构造函数参数传递给 PizzaOrderDialog 类,因为 PizzaOrderDialog 对象将被序列化然后反序列化。

最好的方法是什么?提前致谢!


MessageController.cs

[BotAuthentication]
public class MessagesController : ApiController
{
    private static IForm<PizzaOrder> BuildForm()
    {
        var builder = new FormBuilder<PizzaOrder>();

        ConditionalDelegate<PizzaOrder> isBYO = (pizza) => pizza.Kind == PizzaOptions.BYOPizza;
        ConditionalDelegate<PizzaOrder> isSignature = (pizza) => pizza.Kind == PizzaOptions.SignaturePizza;
        ConditionalDelegate<PizzaOrder> isGourmet = (pizza) => pizza.Kind == PizzaOptions.GourmetDelitePizza;
        ConditionalDelegate<PizzaOrder> isStuffed = (pizza) => pizza.Kind == PizzaOptions.StuffedPizza;

        return builder
            // .Field(nameof(PizzaOrder.Choice))
            .Field(nameof(PizzaOrder.Size))
            .Field(nameof(PizzaOrder.Kind))
            .Field("BYO.Crust", isBYO)
            .Field("BYO.Sauce", isBYO)
            .Field("BYO.Toppings", isBYO)
            .Field(nameof(PizzaOrder.GourmetDelite), isGourmet)
            .Field(nameof(PizzaOrder.Signature), isSignature)
            .Field(nameof(PizzaOrder.Stuffed), isStuffed)
            .AddRemainingFields()
            .Confirm("Would you like a {Size}, {BYO.Crust} crust, {BYO.Sauce}, {BYO.Toppings} pizza?", isBYO)
            .Confirm("Would you like a {Size}, {&Signature} {Signature} pizza?", isSignature, dependencies: new string[] { "Size", "Kind", "Signature" })
            .Confirm("Would you like a {Size}, {&GourmetDelite} {GourmetDelite} pizza?", isGourmet)
            .Confirm("Would you like a {Size}, {&Stuffed} {Stuffed} pizza?", isStuffed)
            .Build()
            ;
    }

    internal static IDialog MakeRoot()
    {
        return new PizzaOrderDialog(BuildForm);
    }

    public async Task<Message> Post([FromBody]Message message)
    {
        return await Conversation.SendAsync(message, MakeRoot);
    }
}

PizzaOrderDialog.cs

[LuisModel("4311ccf1-5ed1-44fe-9f10-a6adbad05c14", "6d0966209c6e4f6b835ce34492f3e6d9")]
[Serializable]
public class PizzaOrderDialog : LuisDialog
{
    private readonly BuildForm<PizzaOrder> MakePizzaForm;

    internal PizzaOrderDialog(BuildForm<PizzaOrder> makePizzaForm)
    {
        this.MakePizzaForm = makePizzaForm;
    }

    [LuisIntent("")]
    public async Task None(IDialogContext context, LuisResult result)
    {
        await context.PostAsync("I'm sorry. I didn't understand you.");
        context.Wait(MessageReceived);
    }

    [LuisIntent("OrderPizza")]
    [LuisIntent("UseCoupon")]
    public async Task ProcessPizzaForm(IDialogContext context, LuisResult result)
    {
        var entities = new List<EntityRecommendation>(result.Entities);
        if (!entities.Any((entity) => entity.Type == "Kind"))
        {
            // Infer kind
            foreach (var entity in result.Entities)
            {
                string kind = null;
                switch (entity.Type)
                {
                    case "Signature": kind = "Signature"; break;
                    case "GourmetDelite": kind = "Gourmet delite"; break;
                    case "Stuffed": kind = "stuffed"; break;
                    default:
                        if (entity.Type.StartsWith("BYO")) kind = "byo";
                        break;
                }
                if (kind != null)
                {
                    entities.Add(new EntityRecommendation("Kind") { Entity = kind });
                    break;
                }
            }
        }

        var pizzaForm = new FormDialog<PizzaOrder>(new PizzaOrder(), this.MakePizzaForm, FormOptions.PromptInStart, entities);
        context.Call<PizzaOrder>(pizzaForm, PizzaFormComplete);
    }

    private async Task PizzaFormComplete(IDialogContext context, IAwaitable<PizzaOrder> result)
    {
        PizzaOrder order = null;
        try
        {
            order = await result;
        }
        catch (OperationCanceledException)
        {
            await context.PostAsync("You canceled the form!");
            return;
        }

        if (order != null)
        {
            await context.PostAsync("Your Pizza Order: " + order.ToString());
        }
        else
        {
            await context.PostAsync("Form returned empty response!");
        }

        context.Wait(MessageReceived);
    }

    enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };

    [LuisIntent("StoreHours")]
    public async Task ProcessStoreHours(IDialogContext context, LuisResult result)
    {
        var days = (IEnumerable<Days>)Enum.GetValues(typeof(Days));

        PromptDialog.Choice(context, StoreHoursResult, days, "Which day of the week?");
    }

    private async Task StoreHoursResult(IDialogContext context, IAwaitable<Days> day)
    {
        var hours = string.Empty;
        switch (await day)
        {
            case Days.Saturday:
            case Days.Sunday:
                hours = "5pm to 11pm";
                break;
            default:
                hours = "11am to 10pm";
                break;
        }

        var text = $"Store hours are {hours}";
        await context.PostAsync(text);

        context.Wait(MessageReceived);
    }
}

最佳答案

您要求执行的操作违反了 MVC 范例。

也就是说 - 你不应该在你的演示( View )层 aka PizzaOrderDialog.cs 的代码中执行一些 Controller 类型的功能并直接与数据库模型交互

你应该在你的 Controller 中注入(inject)一个对你的 db_context 的单例引用(你有那个部分)

在您的 Controller 中添加函数来为对话框封装这些 db_context 交互,然后注入(inject)这些函数的结果,就像您现在使用 BuildForm<PizzaOrder> makePizzaForm 所做的那样。进入对话框构造函数。

即使有人说,基于用户在对话框中选择的内容的 5x4x10 建议 map - 以序列化方式传递整个内容(如您所提到的)并让 PizzaOrderDialog.cs 中的服务器端 View 逻辑与所有可能性 View 模型比尝试公开模型层访问要好。

具体来说,对于订单提交,我会向 Controller 添加一个静态方法,您可以从对话框中调用该方法,再次封装实现这一点所需的与 db_context 的任何交互。

关于c# - 如何将 DbContext(或任何其他对象)注入(inject)对话框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36385681/

相关文章:

python - Microsoft Teams - 机器人主程序中的无限循环

node.js - 微软bot框架网络聊天直连隐藏 secret ——NODE JS

c# - 什么控制 codedom 生成文件中的版本号?

c# - Autofac:使用非泛型接口(interface)注册泛型类型

Autofac取消注册接口(interface)的所有实现

c# - 具有 OWIN 集成的 Autofac 调用了错误的构造函数

C#限制代码量

c# - 用于电子邮件验证的正则表达式不起作用

c# - 捕获事件窗口的屏幕截图?

asp.net-core - 存储在 key 保管库中时未拾取 InstrumentationKey