Dynamic choice field
假設我們現在有個三明治點餐機器人
而點餐的流程是:要求使用者輸入Sandwich種類,大小( Length),以及 Cheese 種類
那底下的Sample code就能滿足我們目前的需求
[ Serializable ]
public class SandwichOrder
{
public SandwichOptions ? Sandwich;
[ Prompt ( "What size do you want? {||}" )]
public LengthOptions ? Length;
[ Optional ]
public CheeseOptions ? Cheese;
public static IForm < SandwichOrder > BuildForm()
{
return new FormBuilder < SandwichOrder >()
.Message( "Welcome to the simple sandwich order bot!" )
.Build();
}
};
public enum SandwichOptions { BLT, BlackForestHam, BuffaloChicken };
public enum LengthOptions { SixInch, FootLong };
public enum CheeseOptions { American, MontereyCheddar, Pepperjack };
|
但如果今天遊戲規則變成:
不同的三明治就有不同的附餐可以選擇
如:
三明治種類 | 副餐選項 |
BLT | cookie, coke |
BlackForestHam | cookie, salard |
BuffaloChicken | coke, salard |
此時程式碼就需要改成根據三明治的種類動態產生附餐的選擇
那我們原先定義的form class裡面就需多宣告一個property 來表達副餐如:
[ Optional ]
[ Template ( TemplateUsage .NoPreference, "None" )]
public string Specials;
|
原來產生Form的程式碼
public static IForm < SandwichOrder > BuildForm()
{
return new FormBuilder < SandwichOrder >()
.Message( "Welcome to the simple sandwich order bot!" )
.Build();
}
|
需改成再透過FormFlow.FormBuilder手動呼叫.Field(IField< T >field) 來產生客製化的field如下
public static IForm < SandwichOrder > BuildForm()
{
return new FormBuilder < SandwichOrder >()
.Message( "Welcome to the simple sandwich order bot!" )
.Field( nameof (Sandwich))
.Field( nameof (Length))
.Field( nameof (Cheese))
.Field( new FieldReflector < SandwichOrder >( nameof (Specials))
.SetType( null )
.SetDefine( async (state, field) =>
{
var dic = GetSpecialFree(state.Sandwich);
foreach ( KeyValuePair < string , string []> item in dic)
{
field
.AddDescription(item.Key, item.Value[0])
.AddTerms(item.Key, item.Value);
}
return true ;
}))
.Build();
}
|
這裡我們使用Advanced.FieldReflector< T >.FieldReflector(string name, bool ignoreAnnotations = false)來替副餐簡單產生一個IField的實體
再加以呼叫Advanced.Field< T >.SetDefine(DefineAsyncDelegate< T > definition )定義副餐field的內容
其中:GetSpecialFree 可以改成去Db裡讀資料, 取出和三明治對應的副餐選擇,
(以下的實作方式是為了簡化說明)
public static Dictionary < string , string []> GetSpecialFree( SandwichOptions ? sandwichOptions)
{
Dictionary < string , string []> dic = new Dictionary < string , string []>();
switch (sandwichOptions)
{
case SandwichOptions .BLT:
dic.Add( "cookie" , new string [] { "Free cookie" , "cookie" });
dic.Add( "drink" , new string [] { "Free drink" , "drink" });
break ;
case SandwichOptions .BlackForestHam:
dic.Add( "cookie" , new string [] { "Free cookie" , "cookie" });
dic.Add( "salard" , new string [] { "Free salard" , "salard" });
break ;
case SandwichOptions .BuffaloChicken:
dic.Add( "drink" , new string [] { "Free drink" , "drink" });
dic.Add( "salard" , new string [] { "Free salard" , "salard" });
break ;
}
return dic;
}
|
結果:
補充I:
若想在某特定條件下才觸發這個選擇
我們可以透過呼叫Advanced.Field< T >.SetActive(ActiveDelegate< T > condition)來達成
.SetActive((state) => state.Length == LengthOptions .FootLong ) |
表示當 state.Length == LengthOptions .FootLong 這個條件成立時才會產生這個field
補充II:
以上的範例也可以改成呼叫. AddRemainingFields()
把定義在form class裡的成員給帶進來
public static IForm < SandwichOrder > BuildForm()
{
return new FormBuilder < SandwichOrder >()
.Message( "Welcome to the simple sandwich order bot!" )
. AddRemainingFields()
.Field( new FieldReflector < SandwichOrder >( nameof (Specials))
.SetType( null )
.SetDefine( async (state, field) =>
{
var dic = GetSpecialFree(state.Sandwich);
foreach ( KeyValuePair < string , string []> item in dic)
{
field
.AddDescription(item.Key, item.Value[0])
.AddTerms(item.Key, item.Value);
}
return true ;
}))
.Build();
}
|
完整的Sample Code
留言
張貼留言