在玩bot framework时,发现他的formflow这部分的设计不错,尤其是attribute和enum的结合使用非常完美。
以下为其代码设计:
public enum SandwichOptions
{
BLT, BlackForestHam, BuffaloChicken, ChickenAndBaconRanchMelt, ColdCutCombo, MeatballMarinara,
OvenRoastedChicken, RoastBeef, RotisserieStyleChicken, SpicyItalian, SteakAndCheese, SweetOnionTeriyaki, Tuna,
TurkeyBreast, Veggie
};
public enum LengthOptions { SixInch, FootLong };
public enum BreadOptions { NineGrainWheat, NineGrainHoneyOat, Italian, ItalianHerbsAndCheese, Flatbread };
public enum CheeseOptions { American, MontereyCheddar, Pepperjack };
public enum ToppingOptions
{
Avocado, BananaPeppers, Cucumbers, GreenBellPeppers, Jalapenos,
Lettuce, Olives, Pickles, RedOnion, Spinach, Tomatoes
};
public enum SauceOptions
{
ChipotleSouthwest, HoneyMustard, LightMayonnaise, RegularMayonnaise,
Mustard, Oil, Pepper, Ranch, SweetOnion, Vinegar
};
[Serializable]
public class SandwichOrder
{
public SandwichOptions? Sandwich;
public LengthOptions? Length;
public BreadOptions? Bread;
public CheeseOptions? Cheese;
public List<ToppingOptions> Toppings;
public List<SauceOptions> Sauce;
public static IForm<SandwichOrder> BuildForm()
{
return new FormBuilder<SandwichOrder>()
.Message("Welcome to the simple sandwich order bot!")
.Build();
}
};
return new FormBuilder<SandwichOrder>()
.Message("Welcome to the sandwich order bot!")
.Field(nameof(Sandwich))
.Field(nameof(Length))
.Field(nameof(Bread))
.Field(nameof(Cheese))
.Field(nameof(Toppings),
validate: async (state, value) =>
{
//..
return result;
})
.Message("For sandwich toppings you have selected {Toppings}.")
.Field(nameof(SandwichOrder.Sauces))
.Field(new FieldReflector<SandwichOrder>(nameof(Specials))
.SetType(null)
.SetActive((state) => state.Length == LengthOptions.FootLong)
.SetDefine(async (state, field) =>
{
field
.AddDescription("cookie", "Free cookie")
.AddTerms("cookie", "cookie", "free cookie")
.AddDescription("drink", "Free large drink")
.AddTerms("drink", "drink", "free drink");
return true;
}))
.Confirm(async (state) =>
{
//..
return new PromptAttribute($"Total for your sandwich is {cost:C2} is that ok?");
})
.Field(nameof(SandwichOrder.DeliveryAddress),
validate: async (state, response) =>
{
//..
return result;
})
.Field(nameof(SandwichOrder.DeliveryTime), "What time do you want your sandwich delivered? {||}")
.Confirm("Do you want to order your {Length} {Sandwich} on {Bread} {&Bread} with {[{Cheese} {Toppings} {Sauces}]} to be sent to {DeliveryAddress} {?at {DeliveryTime:t}}?")
.AddRemainingFields()
.Message("Thanks for ordering a sandwich!")
.OnCompletion(processOrder)
.Build();
在以上代码中,
1. 使用了enum来定义选项信息
2. 使用attribute来做model和enum的粘合剂
3. FormBuilder的流程接口来完成对话的创建
4. FormBuilder通过对分组提问来构造不同的orderDetail对象
...
Message(..)
.Field()
...
.Message("")
.Field(...)
..