从自定义属性属性搜索中解析枚举

时间:2018-01-25 02:27:19

标签: c# botframework

我在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

};

我从一个可以拥有datetimeV2的LUIS意图调用我的CallForm,如下所示:

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

然后我想在CallForm的StartAsync中预先填充它但不知道如何......

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

1 个答案:

答案 0 :(得分:1)

如何执行此操作的示例是通过反射和Attribute.GetCustomAttribute

  

检索应用于的指定类型的自定义属性   程序集,模块,类型成员或方法参数。

扩展方法

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

用法

var callTimeOptions = EnumEx.GetValueFromTerms<CallTimeOptions>("tomorrow noon time");

但是,我认为你不会以正确的方式解决这个问题。

更具前瞻性的系统是使用Dictionary<string,CallTimeOptions>查找搜索字词并将其映射到枚举。

我知道属性看起来很整洁,如果你想扩展这么多可能会运行良好,但是字典可以从db或file加载,而且可能更容易维护(取决于你的要求)