0

Examples, like SandwichBot, use Chain.From to return the IDialog<T> for SendAsync, like this:

    internal static IDialog<SandwichOrder> MakeRootDialog()
    {
        return Chain.From(() => FormDialog.FromForm(SandwichOrder.BuildForm));
    }

I can see that Chain.From pushes and pops the IFormDialog<T>, returned from FormDialog.FromForm, but am not sure what the benefit of that is. However, the chatbot still works without Chain.From, as shown below:

    internal static IDialog<SandwichOrder> MakeRootDialog()
    {
        return FormDialog.FromForm(SandwichOrder.BuildForm);
    }

Since the examples use Chain.From, it makes me think that it might be somehow required or recommended. What is the rationale for Chain.From, where would it be required, and what are the drawbacks to the simpler syntax without it?

Joe Mayo
  • 7,501
  • 7
  • 41
  • 60

1 Answers1

1

In the SimpleSandwichBot I believe that it doesn't make sense to have the Chain.From, however I suspect that was done to allow a seamless transition to the AnnotatedSandwichBot where the Chain is being used a bit more.

Personally I don't use Chain a lot unless I need to put together something really simple and I don't want to create a dialog as it could easily become complex to read/follow.

With Chain you can manage the stack of dialogs implicitly. However, explicit management of the stack of dialogs (using Call/Done) seems to be better to composing larger conversations. Creating new dialogs it's more verbose (especially in C#) but I believe it allows to organize better the solution and the code.

I don't think there is a place where Chain is required as it's not providing anything unique, just a fluent interface that is usable in LINQ query syntax.

The drawbacks I see are mainly around complexity of the resulting code if you are trying to create something big. If I don't misremember, there is also a chance of getting a serialization issue depending how you are using it.

From the docs:

The Chain methods provide a fluent interface to dialogs that is usable in LINQ query syntax. The compiled form of LINQ query syntax often leverages anonymous methods. If these anonymous methods do not reference the environment of local variables, then these anonymous methods have no state and are trivially serializable. However, if the anonymous method captures any local variable in the environment, the resulting closure object (generated by the compiler) is not marked as serializable. The Bot Builder will detect this situation and throw a ClosureCaptureException to help diagnose the issue.

Community
  • 1
  • 1
Ezequiel Jadib
  • 14,767
  • 2
  • 38
  • 43