在查看并逐步浏览源代码后,最简单的答案不是关于 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));
}
}
}
这里的主要思想是创建自己的识别器,因为这是获取原始输入文本的部分。诀窍是知道何时可以创建识别器的实例。必须在设置字段表单之后完成。基础识别器基类将查看构造函数中的字段表单。 (如果您完全放弃使用基础识别器类,这可能不是问题。)
接下来,您可以创建自己的自定义 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();