Bot Framework 在对话框之间再次调用对象的构造函数
Bot Framework is calling constructor of object again between dialogs
大家好,抱歉,这是我第一次发布问题,因为我找不到解决方案。我正在 MS-Bot Framework 中制作聊天机器人并尝试将对象 'Project' 传递给另一个对话框:
return await stepContext.BeginDialogAsync(nameof(searchProject2), new Project(new string[]{"ixnID"}, new string[]{"1"}), cancellationToken);
但是,当我在下一个对话框中执行此操作时,在将消息输入 TextPrompt 后,机器人立即崩溃并且 returns 出现 NullReferenceException 错误:
[OnTurnError] unhandled error : Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
at ixnChatbot.Project..ctor(String[] rawFields, String[] values) in C:\Users\a\ixnChatbot\Models\Project.cs:li
ne 24
at lambda_method(Closure , Object[] )
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 cr
eator, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonPro
perty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract,
JsonProperty containerMember, Object existingValue) .............
调试后我发现构造函数被调用了两次,即使在将 Project 传递到新对话框后我的任何代码都没有访问它。这是它使用的 class 中的构造函数和变量:
protected readonly int ixnID;
private Dictionary<string, int> fields = new Dictionary<string, int>();
private string[] values;
protected string fieldGetterQueryWholeTable
= "SELECT COLUMN_NAME FROM information_schema.columns WHERE table_name in('IXN_database_entries')";
protected string searchQuery;
public Project(string[] rawFields, string[] values)
{
this.values = values;
for (int i = 0; i < rawFields.Length; i++)
{
fields.Add(rawFields[i], i);
}
ixnID = Int32.Parse(values[fields["ixnID"]]);
searchQuery =
"SELECT * FROM IXN_database_entries i WHERE i.ixnID = " + ixnID;
}
这是使用它的瀑布步骤。如您所见,我没有触及传入的对象:
private async Task<DialogTurnResult> oneAsync(WaterfallStepContext stepContext,
CancellationToken cancellationToken)
{
var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("What would you like to know about this project?") };
return await stepContext.PromptAsync(nameof(TextPrompt), promptOptions, cancellationToken);
}
private async Task<DialogTurnResult> twoAsync(WaterfallStepContext stepContext,
CancellationToken cancellationToken)
{
await stepContext.Context.SendActivityAsync(stepContext.Result.ToString());
return await stepContext.ReplaceDialogAsync(InitialDialogId, null, cancellationToken);
}
错误发生在这两个瀑布步骤之间。我能够调试并发现由于某种原因,机器人正在重新调用项目 class 中的构造函数,但第二次调用作为参数传入的列表 'rawField' 是null,这就是它抛出此 NullReference 错误的原因。
我的问题是,如何阻止框架执行此操作?我不明白为什么传入一个对象会导致这种错误,而且在使用像字符串这样的原始类型时似乎不会发生这种错误。我搜索了一段时间,没有发现类似的问题。如有任何帮助,我们将不胜感激!
所以我找到了解决方案(糟糕)以防万一有人遇到这个问题。
我只是在项目class中添加了一个空构造函数,以便在调用它时,其参数不会出现空错误。
public Project()
{
}
这也有效:
[JsonConstructor]
private Project()
{
}
大家好,抱歉,这是我第一次发布问题,因为我找不到解决方案。我正在 MS-Bot Framework 中制作聊天机器人并尝试将对象 'Project' 传递给另一个对话框:
return await stepContext.BeginDialogAsync(nameof(searchProject2), new Project(new string[]{"ixnID"}, new string[]{"1"}), cancellationToken);
但是,当我在下一个对话框中执行此操作时,在将消息输入 TextPrompt 后,机器人立即崩溃并且 returns 出现 NullReferenceException 错误:
[OnTurnError] unhandled error : Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
at ixnChatbot.Project..ctor(String[] rawFields, String[] values) in C:\Users\a\ixnChatbot\Models\Project.cs:li
ne 24
at lambda_method(Closure , Object[] )
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 cr
eator, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonPro
perty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract,
JsonProperty containerMember, Object existingValue) .............
调试后我发现构造函数被调用了两次,即使在将 Project 传递到新对话框后我的任何代码都没有访问它。这是它使用的 class 中的构造函数和变量:
protected readonly int ixnID;
private Dictionary<string, int> fields = new Dictionary<string, int>();
private string[] values;
protected string fieldGetterQueryWholeTable
= "SELECT COLUMN_NAME FROM information_schema.columns WHERE table_name in('IXN_database_entries')";
protected string searchQuery;
public Project(string[] rawFields, string[] values)
{
this.values = values;
for (int i = 0; i < rawFields.Length; i++)
{
fields.Add(rawFields[i], i);
}
ixnID = Int32.Parse(values[fields["ixnID"]]);
searchQuery =
"SELECT * FROM IXN_database_entries i WHERE i.ixnID = " + ixnID;
}
这是使用它的瀑布步骤。如您所见,我没有触及传入的对象:
private async Task<DialogTurnResult> oneAsync(WaterfallStepContext stepContext,
CancellationToken cancellationToken)
{
var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("What would you like to know about this project?") };
return await stepContext.PromptAsync(nameof(TextPrompt), promptOptions, cancellationToken);
}
private async Task<DialogTurnResult> twoAsync(WaterfallStepContext stepContext,
CancellationToken cancellationToken)
{
await stepContext.Context.SendActivityAsync(stepContext.Result.ToString());
return await stepContext.ReplaceDialogAsync(InitialDialogId, null, cancellationToken);
}
错误发生在这两个瀑布步骤之间。我能够调试并发现由于某种原因,机器人正在重新调用项目 class 中的构造函数,但第二次调用作为参数传入的列表 'rawField' 是null,这就是它抛出此 NullReference 错误的原因。
我的问题是,如何阻止框架执行此操作?我不明白为什么传入一个对象会导致这种错误,而且在使用像字符串这样的原始类型时似乎不会发生这种错误。我搜索了一段时间,没有发现类似的问题。如有任何帮助,我们将不胜感激!
所以我找到了解决方案(糟糕)以防万一有人遇到这个问题。
我只是在项目class中添加了一个空构造函数,以便在调用它时,其参数不会出现空错误。
public Project()
{
}
这也有效:
[JsonConstructor]
private Project()
{
}