Bot 框架自定义操作和自定义 ArrayExpression 属性

Bot Framework Custom Action and custom ArrayExpression property

我正在使用 Microsoft 的 Bot Framework Composer 构建一个机器人。为了扩展 composer 的标准功能,我还构建了一些 Custom Actions,包括需要以特定类型的数组形式输入的操作。 这是架构:

{
  "$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
  "$role": "implements(Microsoft.IDialog)",
  "title": "AdvancePropertyTest",
  "description": "Test advanced properties in for custom actions.",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "skillSelectors": {
      "$ref": "schema:#/definitions/arrayExpression",
      "title": "SkillSelector Items",
      "description": "SkillSelector Items.",
      "items": {
        "title": "SkillSelector Item",
        "description": "SkillSelector Item.",
        "type": "object",
        "properties": {
          "key": {
            "title": "Key",
            "description": "The skill key to query against.",
            "type": "string"
          },
          "operator": {
            "title": "Operator",
            "description": "Describes how the value of the label is compared to the value defined on the label selector.",
            "type": "string",
            "enum": [
              "Equal",
              "NotEqual",
              "LessThan",
              "LessThanEqual",
              "GreaterThan",
              "GreaterThanEqual"
            ],
            "default": "Equal"
          },
          "value": {
            "title": "Value",
            "description": "The value to compare against the actual label value with the given operator.",
            "type": "integer"
          }
        }
      }
    }
  }
}

在作曲家中,结果是: Composer action with custom properties

到目前为止,还不错。 现在,在对话框的代码中,为了检索输入数据,这就是我所做的:

[Serializable]
public class SkillSelector
{
    [JsonProperty(PropertyName = "key")]
    public string Key { get; set; }

    [JsonProperty(PropertyName = "operator")]
    public string Operator { get; set; }

    [JsonProperty(PropertyName = "value")]
    public int Value { get; set; }
}


public class AdvancedPropertyTest : Dialog
{
    [JsonProperty("skillSelectors")]
    public ArrayExpression<SkillSelector> SkillSelectors { get; set; }
    //public ArrayExpression<Metadata> SkillSelectors { get; set; }


    public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default)
    {
        var skillSelectors = SkillSelectors?.GetValue(dc.State);
        // some code

        return await dc.EndDialogAsync(cancellationToken: cancellationToken);
    }
}

不幸的是,一旦我 运行 它会导致以下错误消息:

AdvancedProperties.dialog error: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type ‘AdaptiveExpressions.Properties.ArrayExpression`1[SkillSelector]’ because the type requires a JSON object (e.g. {“name”:“value”}) to deserialize correctly.

To fix this error either change the JSON to a JSON object (e.g. {“name”:“value”}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.

Path ‘skillSelectors’, line 49, position 37.

有趣的是,使用 class Microsoft.Bot.Builder.AI.QnA.MetaData 作为 ArrayExpression 中的通用类型就可以了,但是,当然,这不是我想要的。

有人知道如何做到这一点吗? 任何帮助将不胜感激 干杯。

您的属性应该来自 AdaptiveExpressions.Properties。 因此,不要使用字符串 StringExpressionBoolExpression 等:

    [JsonProperty("businessUnitName")]
    public StringExpression BusinessUnitName { get; set; }

    [JsonProperty("reloadData")]
    public BoolExpression ReloadData { get; set; }

获取值:

BusinessUnitName.GetValue(dc.State)

好的,终于找到解决办法了。我在 BotComponent class 的 ConfigureServices 方法中添加了以下行:

public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
    services.AddSingleton<DeclarativeType>(sp => new DeclarativeType<AdvancedPropertyTest>(nameof(AdvancedPropertyTest)));
    services.AddSingleton<JsonConverterFactory, JsonConverterFactory<ArrayExpressionConverter<SkillSelector>>>();
}

这会在 JsonSerializer.

中添加 class SkillSelector

希望这对其他人有帮助。