その他いろいろ
calendar_today
CodeAction を使う
Adaptive Dialog の Action 部分は Dialog クラスをリストにしたりネストにしたりして実装するが、
処理が複雑でそれだと実装しづらい場合は、Microsoft.Bot.Builder.Dialogs.Adaptive.Actions.CodeAction クラスを使って自分でコードを書ける。
CodeAction のコンストラクタに実行させたいメソッドを指定すればよい。
public class RootDialog : AdaptiveDialog
{
    public RootDialog() : base(nameof(RootDialog))
    {
        Triggers = new List<OnCondition>
        {
            new OnConversationUpdateActivity()
            {
                Actions = 
                {
                    new CodeAction(WelcomeUser)
                }
            },
            new OnUnknownIntent
            {
                // 略
            },
        };
    }
    private static async Task<DialogTurnResult> WelcomeUser(DialogContext dc, object options)
    {
        // ここに処理を書く
        return await dc.EndDialogAsync(options);
    }
}
State を読み書きする
CodeAction で State にアクセスする場合は、下記のようにする。
var turnState = (JObject) dc.State["turn"];
メモリのスコープごとに格納されているオブジェクトの方が違う。
- turn - Newtonsoft.Json.Linq.JObject
- dialog - System.Collections.Generic.Dictionary<string, object>
- user - System.Collections.Generic.Dictionary<string, object>
- conversation - System.Collections.Generic.Dictionary<string, object>
など。
大体のスコープは Dictionary 型だが、turn だけなぜか JObject で格納されている。
Welcome メッセージを追加する
ボットから DialogManager を呼び出す処理を OnTurnAsync メソッドに書いたことから分かるように、Adaptive Dialog は全てのイベント、アクティビティに対して処理できる。
ユーザーがボットに初めて接続したときの OnMembersAddedAsync メソッドの処理も Adaptive Dialog へ移せる。
サンプルその1を以下に示す。
public class RootDialog : AdaptiveDialog
{
    public RootDialog() : base(nameof(RootDialog))
    {
        Triggers = new List<OnCondition>
        {
            new OnConversationUpdateActivity()
            {
                Actions = WelcomeUserSteps()
            },
            new OnUnknownIntent
            {
                // 略
            },
        };
    }
    private static List<Dialog> WelcomeUserSteps()
    {
        return new List<Dialog>()
        {
            new Foreach()
            {
                ItemsProperty = "turn.activity.membersAdded",
                Actions = new List<Dialog>()
                {
                    new IfCondition()
                    {
                        Condition = "$foreach.value.name != turn.activity.recipient.name",
                        Actions = new List<Dialog>()
                        {
                            new SendActivity("Hello!")
                        }
                    }
                }
            }
        };
    }
}
WelcomeUserSteps メソッドの内容が Action にあたる。Foreach とか If まで Action クラスになっていて、それらをネストしたりしながら使っていく。
ただこれだとかえって何をやっているかわかりづらいし、ちょっとしたロジックなのに煩雑にみえる。
そういう場合、CodeAction を使うと良い。
public class RootDialog : AdaptiveDialog
{
    public RootDialog() : base(nameof(RootDialog))
    {
        Triggers = new List<OnCondition>
        {
            new OnConversationUpdateActivity()
            {
                Actions = 
                {
                    new CodeAction(WelcomeUser)
                }
            },
            new OnUnknownIntent
            {
                // 略
            },
        };
    }
    private static async Task<DialogTurnResult> WelcomeUser(DialogContext dc, object options)
    {
        foreach (var member in dc.Context.Activity.MembersAdded)
        {
            if (member.Name != dc.Context.Activity.Recipient.Name)
            {
                var message = MessageFactory.Text("Hello!");
                await dc.Context.SendActivityAsync(message);
            }
        }
        return await dc.EndDialogAsync(options);
    }
}