没有“简单”的方法可以做到这一点,但有一种方法。答案将类似于this one https://stackoverflow.com/a/57418517/2122672.
首先,您需要一种保存卡状态的方法,以便可以更新卡的活动。在 C# 中,您可以像这样声明状态属性访问器:
public IStatePropertyAccessor<Dictionary<string, (string ActivityId, List<string> Shots)>> BattleshipStateAccessor { get; internal set; }
然后你可以像这样实例化它
BattleshipStateAccessor = _conversationState.CreateProperty<Dictionary<string, (string, List<string>)>>("battleshipState");
您需要在这里做出一些决定。首先,我选择将状态属性设置为字典,以便我可以跟踪多张卡片并仅更新单击的特定卡片。如果您不关心这一点,那么您不需要字典,也不需要担心“卡 ID”,但至少需要保存一个活动 ID,以便您能够更新卡。至于保存“镜头”,您有几个选择。您可以通过在每次拍摄时更新提交操作的数据来在客户端保存该状态,但我认为我也可以将拍摄保存在机器人状态中,因为无论如何我已经需要将活动 ID 保存在机器人状态中。接下来的问题是您应该保存每个镜头的哪些信息。在这个例子中,我只保存用户输入的镜头位置,而不是镜头状态,因为我认为我可以在需要时随时重新计算状态。
我已将您的提交操作修改为如下所示:
{
"type": "Action.Submit",
"title": "Shoot",
"style": "positive",
"data": {
"behavior": "Shoot",
"cardId": ""
}
}
我在这里所做的是将两个属性添加到您的数据对象,并且该数据将与文本输入的值一起发送到您的机器人。如果您的机器人使用可以以不同方式处理的多种类型的操作,“行为”属性将帮助您的机器人路由到正确的功能。 “cardId”属性只是一个占位符,您的机器人代码将在创建卡片时填充该占位符。我已将这些属性的名称存储在常量中KEYBEHAVIOR
and KEYCARDID
.
您需要采用一致的方式来生成卡片,以便在最初发送卡片和更新卡片时使用。
internal static IMessageActivity CreateBattleshipCardActivity(
string cardId,
object data = null)
{
data = data ?? new
{
name = "Test shot",
shoots = new string[0],
};
JObject card = CreateAdaptiveCard("battleship", data);
foreach (var token in card.Descendants()
.Select(token => token as JProperty)
.Where(token => token?.Name == KEYCARDID))
{
token.Value = cardId;
}
return MessageFactory.Attachment(new Attachment(
AdaptiveCard.ContentType,
content: card));
}
The CreateAdaptiveCard
函数从具有给定名称的文件加载 JSON 模板,使用给定数据对其进行转换,并将其反序列化为JObject
.
使用此函数,您可以在 C# 中像这样最初发送卡片:
public async Task TestBattleshipAsync(
ITurnContext turnContext,
CancellationToken cancellationToken)
{
var activity = turnContext.Activity;
var cardId = Guid.NewGuid().ToString();
var reply = CreateBattleshipCardActivity(cardId);
var response = await turnContext.SendActivityAsync(reply, cancellationToken);
var dict = await BattleshipStateAccessor.GetAsync(
turnContext,
() => new Dictionary<string, (string, List<string>)>(),
cancellationToken);
dict[cardId] = (response.Id, new List<string>());
}
您可以更新卡以响应卡的“拍摄”提交操作,如下所示:
private async Task ShootAsync(
ITurnContext turnContext,
CancellationToken cancellationToken)
{
var activity = turnContext.Activity;
if (activity.ChannelId == Channels.Msteams)
{
var value = JObject.FromObject(activity.Value);
var cardId = Convert.ToString(value[BotUtil.KEYCARDID]);
var dict = await BattleshipStateAccessor.GetAsync(
turnContext,
() => new Dictionary<string, (string, List<string>)>(),
cancellationToken);
if (dict.TryGetValue(cardId, out var savedInfo))
{
savedInfo.Shots.Add(value["id_shoot"].ToString());
var data = new
{
name = "Test shot",
shoots = savedInfo.Shots.Select(shot => new
{
shoot = shot,
status = DetermineHit(shot),
}),
};
var update = CreateBattleshipCardActivity(cardId, data);
update.Id = savedInfo.ActivityId;
update.Conversation = activity.Conversation;
await turnContext.UpdateActivityAsync(update, cancellationToken);
}
}
}