I have the following enum used in CallForm FormDialog:
public enum CallTimeOptions
{
[Describe("tonight")]
[Terms("tonight", "this evening", "pm", "this pm")]
Tonight = 1,
[Describe("tomorrow morning")]
[Terms("tomorrow morning", "tomorrow am", "am")]
TomorrowMorning,
[Describe("tomorrow noon time")]
[Terms("tomorrow noon time", "tomorrow noon", "tomorrow lunch", "lunch")]
TomorrowNoonTime,
[Describe("tomorrow evening")]
[Terms("tomorrow evening", "tomorrow pm", "tomorrow night")]
TomorrowEvening
};
I am calling my CallForm from a LUIS intent that can have a datetimeV2 so something like this:
[LuisIntent("Call")]
public async Task Call(IDialogContext context, LuisResult result)
{
EntityRecommendation entityRecommendation;
if (result.TryFindEntity("builtin.datetimeV2.datetimerange", out entityRecommendation))
{
context.UserData.SetValue<string>(ContextKeys.CallTimeOption, entityRecommendation.Entity);
}
context.UserData.Call(new CallForm(), CallFormResumeAfter);
}
Then I want to prefill it in StartAsync of CallForm but don't know how...
public async Task StartAsync(IDialogContext context)
{
var state = new CallTimeForm();
string calltime;
if(context.UserData.TryGetValue(ContextKeys.CallTimeOption, out calltime))
{
state.PreferredCallTime = -- is there a way to match calltime with CallTimeOptions ? --
}
var form = new FormDialog<CallTimeForm>(
state,
BuildForm,
FormOptions.PromptInStart);
context.Call(form, this.AfterBuildForm);
}
An example of how to do this is via reflection and Attribute.GetCustomAttribute
Retrieves a custom attribute of a specified type applied to an assembly, module, type member, or method parameter.
method
public static class EnumEx
{
public static T GetValueFromTerms<T>(string value)
{
var type = typeof(T);
if (!type.IsEnum)
{
throw new InvalidOperationException();
}
foreach (var field in type.GetFields())
{
if (Attribute.GetCustomAttribute(field, typeof(TermsAttribute)) is TermsAttribute attribute)
{
// Search your attribute array or properties here
// Depending on the structure of your attribute
// you will need to change this if Conidition
if (attribute.ContainsTerms(value))
{
return (T)field.GetValue(null);
}
}
else
{
if (field.Name == value)
{
return (T)field.GetValue(null);
}
}
}
throw new ArgumentException("Not found.", nameof(value));
// or return default(T);
}
}
Usage
var callTimeOptions = EnumEx.GetValueFromTerms<CallTimeOptions>("tomorrow noon time");
However, I think you are not going about this the right way.
A more future proofed system would be to use a Dictionary<string,CallTimeOptions>
to look up search terms and map them to enums.
I know attributes seems neat and might work well if you arnt going to expand this much, however a dictionary could be loaded form db or file, and it might just be easier to maintain (depending on your requirements)