その他いろいろ
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);
}
}