使用AlarmBot Sample和Improved Sandwich Bot,我试图了解如何将FormBuilder与自定义对话框行为相结合。具体来说,我想采用Alarm Bot SetAlarm方法
SetAlarm(IDialogContext context, LuisResult result)
并在SandwichBot中使用相同的Chronic.Parser作为DeliveryTime字段。怎么办?我已经看过实施IField,但我不确定它会是什么样子。
答案 0 :(得分:2)
查看并逐步查看源代码后,最简单的答案与IFieldState无关。关键接口是IRecognize。正确使用它需要了解一些正在进行的内容。
首先创建自己的自定义字段。该框架很好地允许我们从FieldReflector派生,它完成了大部分工作。
public class BetterDateTimeField : FieldReflector<MyOrder>
{
public BetterDateTimeField(string name, bool ignoreAnnotations = false)
: base(name, ignoreAnnotations) { }
public override IForm<MyOrder> Form
{
set
{
base.Form = value;
base.SetRecognizer(new BetterDateTimeRecognizer<MyOrder>(this, CultureInfo.CurrentCulture));
}
}
}
这里的主要想法是创建自己的识别器,因为这是获取原始输入文本的部分。诀窍是知道何时可以创建识别器的实例。必须完成 AFTER 已设置字段表单。底层的Recognizer基类将查看构造函数中的fields表单。 (如果您完全放弃使用基本的识别器类,这可能不是问题。)
接下来,您可以创建自己的自定义IRecognize实现。不幸的是,僵尸框架密封了许多基本/原始类型识别器类,因此从RecognizeDateTime派生并且重载Parse不是一个选项(希望有一天他们会解封它们)。但是,复制和编辑到您自己的自定义类中非常容易。
using Chronic;
public class BetterDateTimeRecognizer<T> : RecognizePrimitive<T> where T : class
{
private CultureInfo _culture;
private Parser _parser;
public BetterDateTimeRecognizer(IField<T> field, CultureInfo culture)
: base(field)
{
_culture = culture;
_parser = new Chronic.Parser();
}
public override string Help(T state, object defaultValue)
{
var prompt = new Prompter<T>(_field.Template(TemplateUsage.DateTimeHelp), _field.Form, null);
var args = HelpArgs(state, defaultValue);
return prompt.Prompt(state, _field.Name, args.ToArray());
}
public override TermMatch Parse(string input)
{
TermMatch match = null;
// the original code
//DateTime dt;
//if (DateTime.TryParse(input, out dt))
//{
// match = new TermMatch(0, input.Length, 1.0, dt);
//}
var parse = _parser.Parse(input);
if (parse != null && parse.Start.HasValue)
{
match = new TermMatch(0, input.Length, 1.0, parse.Start.Value);
}
return match;
}
public override IEnumerable<string> ValidInputs(object value)
{
yield return ValueDescription(value);
}
public override string ValueDescription(object value)
{
return ((DateTime)value).ToString(CultureInfo.CurrentCulture.DateTimeFormat);
}
}
最后,您只需将其连接到BuildForm()中的表单构建器:
var form = builder.Message("Hello there. What can I help you today")
.Field(new BetterDateTimeField("<NAME of YOUR DateTime Field HERE>")
.Build();
答案 1 :(得分:1)
最初我们在FormFlow中使用Chronic for DateTime字段,但是当我们转移到签署我们的dll时,我们再也无法使用未签名的C#Chronic库。我已经联系了作者但要求他签名,但还没有回复 - 如果他这样做,我们会把它作为FormFlow的一部分。
至于实现IField,如果您愿意,可以从Field派生并提供您自己的IFieldState实现。 Field具有所有声明性内容的数据结构,您可以覆盖所有方法。这将允许您在未签名的DLL中使用Chronic。