When you look at the samples for the Bot Framework you’ll no doubt see a pattern for the root dialog that looks like this;
public MyBot(MyBotAccessors accessors, ILoggerFactory loggerFactory) { Dialogs = new DialogSet(accessors.DialogState); Dialogs.Add(new DialogA()); Dialogs.Add(new DialogB()); ... Dialogs.Add(new DialogN()); }
The great thing about the above pattern is that it is nice and clean, you know that the dialog set will be correctly initialized and therefore when you call var dialogResult = await dialogContext.ContinueDialogAsync
or await dialogContext.BeginDialogAsync
everything will just work.
The problem with the above is that the MyBot constructor will be called for every message that the bot receives. Therefore, every new DialogX
will also be called. If you have a reasonably feature rich bot then this overhead might become a problem, especially if the constructors are doing anything…I mean you never write your constructor to do anything slow…right? Regardless I wanted to see if the overhead could be avoided…it can.
public MyBot(MyBotAccessors accessors, ILoggerFactory loggerFactory) { // Initialize like before Dialogs = new DialogSet(accessors.DialogState); } public async Task OnTurnAsync(ITurnContext turnContext) { ... // (skipping code to focus) var dialogContext = await Dialogs.CreateContextAsync(turnContext); // the context is loaded from state, regardless of our instances // so we can see what the Active Dialog Id and... if (dialogContext.ActiveDialog?.Id == "DialogB") { // create in JIT Dialogs.Add(new DialogB()); } ... // remember you'll also have to JIT to invoke the dialog // don't add it twice Dialogs.Add(new DialogB()); await dialogContext.BeginDialogAsync(nameof(DialogB)); }