2016-04-01 6 views
1

AlarmBot SampleImproved Sandwich Botを使用して、FormBuilderをカスタムダイアログの動作と組み合わせる方法を理解しようとしています。具体的には、私はアラームボットSetAlarm方法Microsoft Bot FrameworkのFormBuilderを使用したカスタムフィールド

SetAlarm(IDialogContext context, LuisResult result) 

を取り、出荷までのフィールドのSandwichBotで同じChronic.Parserを活用したいです。それはどうやって行なわれるのですか?私はIFieldの実装を見てきましたが、どのように見えるか分かりません。

答えて

1

元々はFormFlowのDateTimeフィールドにChronicを使用しましたが、私たちがdllに署名するために移動したときに、署名のないC#Chronicライブラリを使用できなくなりました。私は著者に署名してもらうように依頼しましたが、まだ聞いていませんでした。もし彼がそれをFormFlowの一部にするでしょう。

IFieldの実装に関しては、Fieldから派生して独自のIFieldStateの実装を提供できます。フィールドには宣言的なものすべてのデータ構造があり、すべてのメソッドをオーバーライドすることができます。これにより、署名のないDLLでChronicを使用することができます。

+0

それよりも複雑であるように思われます。派生すると、(たとえソースをデバッガでステップ実行しても)プロンプトやその他の不明な項目を設定する必要があるようです。 – DigitalEd

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の基底クラスは、コンストラクタのフィールドフォームを調べます。 (ベースレコグナイザクラスを完全に放棄した場合、これは問題ではない可能性があります)

次に、独自のカスタムIRecognize実装を作成できます。残念ながら、ボットフレームワークは、基本/プリミティブ型レコグナイザクラスの多くをシールするので、RecognizeDateTimeから派生し、パーズのオーバーロードはオプションではありません(おそらくいつかはそれらをアンシールします)。ただし、独自のカスタムクラスにコピーして編集するだけでも簡単です。

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

また、元のフィールドがBetterDateTimeField である可能性があることを追加する必要があります。それはおそらく同様に機能し、より一般的な解決策です。 – DigitalEd

関連する問題