【问题标题】:Bot Framework - Luis Dialog - Set the LuisModel attribute from Web.configBot Framework - Luis 对话框 - 从 Web.config 设置 LuisModel 属性
【发布时间】:2018-09-28 14:54:04
【问题描述】:

我正在基于 LUIS 在 Microsoft Bot Framework 中编写聊天机器人。 (这是我第一次使用 LUIS)。我有一个基本的 LuisDialog 类,我想在其中设置 LuisModel 属性。 问题是,定义 LuisModel 需要常量值。我想从 Web.config 文件中检索这些值。

这失败了,我收到一条错误消息,提示“属性参数必须是属性参数类型的常量表达式、typeof 表达式或数组创建表达式”。 (这是因为从 Web.config 文件中检索值。)

有没有办法从 Web.config 文件中检索这些值并在属性中设置它们?

我尝试了以下解决方案,但没有成功:

[Serializable]
[LuisModel(Constants.LuisModelId, Constants.LuisSubscriptionKey)]
public class LuisDialog : LuisDialog<object>
{
    //...
}

internal static class Constants
{
    internal const string LuisModelId = WebConfigurationManager.AppSettings.Get("LuisModelId");
    internal const string LuisSubscriptionKey = WebConfigurationManager.AppSettings.Get("LuisSubscriptionKey");
}

【问题讨论】:

    标签: c# botframework constants azure-language-understanding


    【解决方案1】:

    您不能直接在 web.config 中的属性上设置它们,因为属性是在编译时评估的。

    但是,您可以做到。 LuisDialog 类构造函数采用 ILuisService 参数。

    public LuisDialog(params ILuisService[] services)
    

    现在,ILuisService 有一个适当命名的默认实现 LuisService,它有一个构造函数,该构造函数接受一个 ILuisModel 参数

    public LuisService(ILuisModel model)
    

    请耐心等待,我要讲好东西了。 ILuisModel 是在 LuisModelAttribute 类中实现的。

    public class LuisModelAttribute : Attribute, ILuisModel, ILuisOptions, IEquatable<ILuisModel>
    

    在 LuisModelAttributes 构造函数中,您应该开始了解它的去向

    public LuisModelAttribute(string modelID, string subscriptionKey,
            LuisApiVersion apiVersion = LuisApiVersion.V2, string domain = null, double threshold = 0.0d)
    

    这个构造函数接受一个modelId和subscriptionKey!这正是您正在寻找的。 现在,下一个问题是您如何将所有这些放在一起?答案是使用 autofac 进行依赖注入。

    我通常为我的所有 DI 注册声明一个新的 Autofac 模型类。

    internal sealed class MainModule : Module
    

    我们需要注册的第一件事是 LuisModelAttribute 的一个实例

    var luisModelAttr = new LuisModelAttribute(ConfigurationManager.AppSettings["luis:AppId"],
        ConfigurationManager.AppSettings["luis:ServiceKey"],
        LuisApiVersion.V2,
        ConfigurationManager.AppSettings["luis:APIHostName"])
    {
        BingSpellCheckSubscriptionKey = ConfigurationManager.AppSettings["luis:BingSpellCheckKey"],
        SpellCheck = true
    }
    

    这并没有注册任何东西,它只是创建了一个 LuisModelAttribute 类的实例。现在,注册它。

    builder.Register(c => luisModelAttr).AsSelf().AsImplmentedInterface().SingleInstance();
    

    接下来,注册你的 Luis 对话框,你需要在构造函数参数中包含 ILuisService

    builder.Register(c => new MyLuisDialog(c.Resolve<ILuisService>())
        .As<IDialog<IMessageActivity>>()
        .InstancePerDependency();
    

    LuisService 的最后一次注册,或者在我们的例子中是 ILuisService

    builder.RegisterType<LuisService>()
        .Keyed<ILuisService>(FiberModule.Key_DoNotSerilialize)
        .AsImplementedInterface()
        .SingleInstance();
    

    那么,这里发生了什么?因为 LuisModelAttribute 实现了 ILuisModel,Autofac 会知道将 Lu​​isModelAttribute 作为 LuisService 的参数包含在内,并且会知道将实现 ILuisService 的 LuisService 包含到我们的 luis 对话框 MyLuisDialog 中。

    您的具体实现可能会有所不同,但此示例将为您提供所需的内容。祝你好运!

    【讨论】:

    • 感谢您提供如此详细的回答!我经历了您编写、实施的步骤,最终得到了所需的结果。
    • 太棒了!很高兴能帮到你。
    【解决方案2】:

    创建自定义 LuisModelAttribute

      public sealed class CustomLuisAttribute : LuisModelAttribute
        {
            public CustomLuisAttribute(string modelID, string subscriptionKey, LuisApiVersion apiVersion = LuisApiVersion.V2, string domain = null, double threshold = 0) 
                : base(modelID : ConfigurationManager.AppSettings["ModelId"], subscriptionKey : ConfigurationManager.AppSettings["LuisSubscriptionKey"])
            {
            }
        }
    
    

    将其用作根对话框的属性

    [CustomLuisAttribute]
    [Serializable]
    public class RootDialog : LuisDialog<object>
    {
    }
    

    【讨论】:

      猜你喜欢
      • 2017-07-18
      • 2018-10-06
      • 2017-11-19
      • 2019-11-01
      • 1970-01-01
      • 2017-04-27
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多