假设我想在这个例子中将订单保存到数据库 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/