对话链的问题
Trouble with dialog chains
所以我有这样的对话链...
public static readonly IDialog<string> dialog = Chain.PostToChain()
.Select(msg => msg.Text)
.Switch(
new RegexCase<IDialog<string>>(new Regex("^hi", RegexOptions.IgnoreCase), (context, txt) =>
{
return Chain.ContinueWith(new GreetingDialog(),
async (ctx, res) =>
{
var token = await res;
var name = "User";
context.UserData.TryGetValue<string>("Name", out name);
return Chain.Return($"You are logged in as: {name}");
});
}),
new DefaultCase<string, IDialog<string>>((context, txt) =>
{
int count;
context.UserData.TryGetValue("count", out count);
context.UserData.SetValue("count", ++count);
string reply = string.Format("{0}: You said {1}", count, txt);
return Chain.Return(reply);
}))
.Unwrap()
.PostToUser();
对话框如下所示
[Serializable]
public class GreetingDialog : IDialog
{
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Hi I'm John Bot");
context.Wait(MessageReceivedAsync);
}
public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
var userName = String.Empty;
var getName = false;
context.UserData.TryGetValue<string>("Name", out userName);
context.UserData.TryGetValue<bool>("GetName", out getName);
if (getName)
{
userName = message.Text;
context.UserData.SetValue<string>("Name", userName);
context.UserData.SetValue<bool>("GetName", false);
}
if (string.IsNullOrEmpty(userName))
{
await context.PostAsync("What is your name?");
context.UserData.SetValue<bool>("GetName", true);
}
else
{
await context.PostAsync(String.Format("Hi {0}. How can I help you today?", userName));
}
context.Wait(MessageReceivedAsync);
}
}
当我尝试 运行 时,我得到一个错误 "Exception: Microsoft.Bot.Builder.Internals.Fibers.ClosureCaptureException: anonymous method closures that capture the environment are not serializable, consider removing environment capture or using a reflection serialization surrogate"
有人能指出我正确的方向吗?我不确定我在这里做错了什么。
问题似乎与以下匿名方法有关:
async (ctx, res) =>
{
var token = await res;
var name = "User";
context.UserData.TryGetValue<string>("Name", out name);
return Chain.Return($"You are logged in as: {name}");
});
尝试用一种方法代替它:
return Chain.ContinueWith(new GreetingDialog(), AfterGreetingContinuation);
private async static Task<IDialog<string>> AfterGreetingContinuation(IBotContext context, IAwaitable<object> res)
{
var token = await res;
var name = "User";
context.UserData.TryGetValue<string>("Name", out name);
return Chain.Return($"You are logged in as: {name}");
}
但是,请注意,在您 "end" 带有 context.Done() 的 GreetingDialog 之前,可能不会调用延续方法。
所以我有这样的对话链...
public static readonly IDialog<string> dialog = Chain.PostToChain()
.Select(msg => msg.Text)
.Switch(
new RegexCase<IDialog<string>>(new Regex("^hi", RegexOptions.IgnoreCase), (context, txt) =>
{
return Chain.ContinueWith(new GreetingDialog(),
async (ctx, res) =>
{
var token = await res;
var name = "User";
context.UserData.TryGetValue<string>("Name", out name);
return Chain.Return($"You are logged in as: {name}");
});
}),
new DefaultCase<string, IDialog<string>>((context, txt) =>
{
int count;
context.UserData.TryGetValue("count", out count);
context.UserData.SetValue("count", ++count);
string reply = string.Format("{0}: You said {1}", count, txt);
return Chain.Return(reply);
}))
.Unwrap()
.PostToUser();
对话框如下所示
[Serializable]
public class GreetingDialog : IDialog
{
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Hi I'm John Bot");
context.Wait(MessageReceivedAsync);
}
public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
var userName = String.Empty;
var getName = false;
context.UserData.TryGetValue<string>("Name", out userName);
context.UserData.TryGetValue<bool>("GetName", out getName);
if (getName)
{
userName = message.Text;
context.UserData.SetValue<string>("Name", userName);
context.UserData.SetValue<bool>("GetName", false);
}
if (string.IsNullOrEmpty(userName))
{
await context.PostAsync("What is your name?");
context.UserData.SetValue<bool>("GetName", true);
}
else
{
await context.PostAsync(String.Format("Hi {0}. How can I help you today?", userName));
}
context.Wait(MessageReceivedAsync);
}
}
当我尝试 运行 时,我得到一个错误 "Exception: Microsoft.Bot.Builder.Internals.Fibers.ClosureCaptureException: anonymous method closures that capture the environment are not serializable, consider removing environment capture or using a reflection serialization surrogate"
有人能指出我正确的方向吗?我不确定我在这里做错了什么。
问题似乎与以下匿名方法有关:
async (ctx, res) =>
{
var token = await res;
var name = "User";
context.UserData.TryGetValue<string>("Name", out name);
return Chain.Return($"You are logged in as: {name}");
});
尝试用一种方法代替它:
return Chain.ContinueWith(new GreetingDialog(), AfterGreetingContinuation);
private async static Task<IDialog<string>> AfterGreetingContinuation(IBotContext context, IAwaitable<object> res)
{
var token = await res;
var name = "User";
context.UserData.TryGetValue<string>("Name", out name);
return Chain.Return($"You are logged in as: {name}");
}
但是,请注意,在您 "end" 带有 context.Done() 的 GreetingDialog 之前,可能不会调用延续方法。