Я создаю некоторые динамические «сообщения», которые могут быть собраны и объединены во время выполнения.
У меня есть следующие классы
[Serializable]
[JsonObject(IsReference = true)]
public class Node : INode
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
public virtual bool WaitForInput { get; set; }
public virtual int OnCompleteID { get; set; }
public virtual string OnCompleteName { get; set; }
public virtual Node OnCompleteNode { get; set; }
public virtual async Task OnExcecute(IDialogContext context, Activity activity)
{
if (OnCompleteNode != null)
if (WaitForInput)
context.Wait(OnCompleteNode.OnExcecuteAwait);
else
await OnCompleteNode.OnExcecute(context, activity);
}
public virtual async Task OnExcecuteAwait(IDialogContext context, IAwaitable<object> result)
{
Activity activity = await result as Activity;
await OnExcecute(context, activity);
}
}
, которые наследует следующий класс:
public class MessageNode : Node
{
/*public override int ID { get; set; }
public override string Name { get; set; }
public override bool WaitForInput { get; set; }
public override int OnCompleteID { get; set; }
public override string OnCompleteName { get; set; }
public override Node OnCompleteNode { get; set; }*/
public virtual string Message { get; set; }
public virtual List<Attachment> Attachments { get; set; }
public virtual string AttachmentLayoutType { get; set; }
public override async Task OnExcecute(IDialogContext context, Activity activity)
{
IMessageActivity reply = context.MakeMessage();
reply.Text = Message;
if (Attachments != null)
{
reply.Attachments = Attachments;
reply.AttachmentLayout = AttachmentLayoutType;
}
await context.PostAsync(reply);
await base.OnExcecute(context, activity);
}
}
Наконец, я собираю данные в моем RootDialog
public Task StartAsync(IDialogContext context)
{
Schema.MessageNode preMN1 = new Schema.MessageNode();
preMN1.Message = "and then one more";
preMN1.ID = 2;
preMN1.WaitForInput = true;
Schema.MessageNode preMN = new Schema.MessageNode();
preMN.Message = "and then";
preMN.ID = 1;
preMN.OnCompleteNode = preMN1;
preMN.WaitForInput = true;
Schema.MessageNode messageNode = new Schema.MessageNode();
messageNode.Message = "test";
messageNode.ID = 0;
messageNode.OnCompleteNode = preMN;
messageNode.WaitForInput = true;
preMN1.OnCompleteNode = messageNode;
string jTest = JsonConvert.SerializeObject(messageNode);
context.Wait(messageNode.OnExcecuteAwait);
return Task.CompletedTask;
}
В настоящее время сначала вызывается OnExcecuteAwait messageNode.Который отображает «тест» в чате, пока все хорошо.Поскольку флаг WaitForInput имеет значение true, следующий узел в цепочке (preMN) вызывается с context.Wait.Когда пользователь отвечает вводом, текст «и затем» отправляется по желанию, но не перемещается к следующему узлу в цепочке.Он застревает в preMN и продолжает цикл.После отладки я обнаружил, что свойство OnCompleteNode (вместе со всеми виртуальными свойствами, определенными в родительском классе Node) было очищено.
Странно, если я переопределил виртуальные свойства в классе MessageNode, то context.Wait полностью сломался, а ботпостоянно возвращается к RootDialog.Однако, если я тогда удалю строку "preMN1.OnCompleteNode = messageNode;"Поведение работает отлично, и бот оказывается на последнем узле, как и ожидалось.Я полагаю, что это может быть связано с некоторым предотвращением циклов при сериализации состояния бота, но в идеале я хотел бы иметь возможность вернуться к предыдущему сообщению, если это необходимо.