2016-04-01 3 views
1

Mithilfe der AlarmBot Sample und der Improved Sandwich Bot, ich versuche zu verstehen, wie Sie den FormBuilder mit benutzerdefinierten Dialogfeld Verhalten kombinieren. Insbesondere möchte ichBenutzerdefinierte Felder mit FormBuilder im Microsoft Bot Framework

SetAlarm(IDialogContext context, LuisResult result) 

und nutzen die gleiche Chronic.Parser im SandwichBot für den Versand innerhalb Feld der Alarm Bot Einst Methode nehmen. Wie wäre das zu machen? Ich habe versucht, IField zu implementieren, aber ich bin mir nicht sicher, wie es aussehen würde.

Antwort

1

Ursprünglich verwendeten wir Chronic für DateTime-Felder in FormFlow, aber als wir zur Signierung unserer DLL übergingen, konnten wir die nicht signierte C# -Chonic-Bibliothek nicht mehr verwenden. Ich habe mich zwar an den Autor gewandt, um ihn zu bitten, es zu unterschreiben, aber ich habe es noch nicht gehört - wenn er es tut, werden wir es zu einem Teil von FormFlow machen.

Wenn Sie IField implementieren möchten, können Sie von Field ableiten und Ihre eigene Implementierung von IFieldState bereitstellen. Das Feld hat Datenstrukturen für alle deklarativen Elemente und Sie können alle Methoden überschreiben. Auf diese Weise können Sie Chronic in Ihrer nicht signierten DLL verwenden.

+0

Es erscheinen würde als komplizierter zu sein. Das Ableiten erfordert das Einrichten von Eingabeaufforderungen und anderen Elementen, die unklar sind (selbst wenn Sie mit dem Debugger durch die Quelle gehen). – DigitalEd

2

Nachdem Sie die Quelle durchsucht und durch sie gegangen sind, ist die einfachste Antwort nicht der IFieldState. Die Schlüsselschnittstelle ist IRecognize. Um es korrekt zu verwenden, muss man ein wenig verstehen, was unter den Abdeckungen passiert.

Beginnen Sie mit der Erstellung eines eigenen benutzerdefinierten Feldes. Das Framework ermöglicht uns die Ableitung vom FieldReflector, der die meiste Arbeit erledigt.

Die Hauptidee hier ist, Ihre eigene Erkennung zu erstellen, da das der Teil ist, der den rohen Eingabetext erhält. Der Trick besteht darin zu wissen, wann Sie eine Instanz des Recognizers erstellen können. Es muss getan werden NACH das Feld Formular wurde festgelegt. Die zugrundeliegende Recognizer-Basisklasse wird die Form des Feldes im Konstruktor betrachten. (Wenn Sie die Verwendung der Basis-Recognizer-Klassen vollständig beenden, stellt dies möglicherweise kein Problem dar.)

Als Nächstes können Sie Ihre eigene benutzerdefinierte IRecognize-Implementierung erstellen. Leider versiegelt das Bot-Framework viele der Recognizer-Klassen des Basis-/Primitivtyps, die von RecognizeDateTime abgeleitet sind, und das Überladen von Parse ist keine Option (hoffentlich werden sie sie eines Tages freigeben). Es ist jedoch einfach genug, in Ihre eigene benutzerdefinierte Klasse zu kopieren und zu bearbeiten.

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); 
    } 
} 

Schließlich Sie müssen es nur in BuildForm zu Ihrem Formular-Builder verkabeln():

var form = builder.Message("Hello there. What can I help you today") 
      .Field(new BetterDateTimeField("<NAME of YOUR DateTime Field HERE>") 
      .Build(); 
+1

Ich sollte auch hinzufügen, dass das ursprüngliche Feld BetterDateTimeField hätte sein können. Das funktioniert wahrscheinlich genauso gut und ist eine allgemeinere Lösung. – DigitalEd

Verwandte Themen