Bot Framework - Luis Dialog - 从 Web.config 设置 LuisModel 属性
Bot Framework - Luis Dialog - Set the LuisModel attribute from Web.config
我正在基于 LUIS 在 Microsoft Bot Framework 中编写聊天机器人。 (这是我第一次使用 LUIS)。我有一个基本的 LuisDialog class,我想在其中设置 LuisModel 属性。
问题是,定义 LuisModel 需要常量值。我想从 Web.config 文件中检索这些值。
这失败了,我收到一条错误消息说 "An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type"。 (这是因为从 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");
}
您不能直接在 web.config 的属性上设置它们,因为属性是在编译时评估的。
但是,你可以做到。
LuisDialog class 构造函数接受 ILuisService 的参数。
public LuisDialog(params ILuisService[] services)
现在,ILuisService 有一个名为 LuisService 的默认实现,它有一个采用 ILuisModel 参数的构造函数
public LuisService(ILuisModel model)
请耐心等待,我要讲好东西了。 ILuisModel 是在 class 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 模型 class。
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 class 的一个实例。现在,注册它。
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 将知道将我们的 LuisModelAttribute 作为 LuisService 的参数包含在内,并且将知道将实现 ILuisService 的 LuisService 包含到我们的 luis 对话框 MyLuisDialog 中。
您的具体实现可能会有所不同,但此示例将为您提供所需的内容。祝你好运!
创建自定义 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>
{
}
我正在基于 LUIS 在 Microsoft Bot Framework 中编写聊天机器人。 (这是我第一次使用 LUIS)。我有一个基本的 LuisDialog class,我想在其中设置 LuisModel 属性。 问题是,定义 LuisModel 需要常量值。我想从 Web.config 文件中检索这些值。
这失败了,我收到一条错误消息说 "An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type"。 (这是因为从 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");
}
您不能直接在 web.config 的属性上设置它们,因为属性是在编译时评估的。
但是,你可以做到。 LuisDialog class 构造函数接受 ILuisService 的参数。
public LuisDialog(params ILuisService[] services)
现在,ILuisService 有一个名为 LuisService 的默认实现,它有一个采用 ILuisModel 参数的构造函数
public LuisService(ILuisModel model)
请耐心等待,我要讲好东西了。 ILuisModel 是在 class 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 模型 class。
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 class 的一个实例。现在,注册它。
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 将知道将我们的 LuisModelAttribute 作为 LuisService 的参数包含在内,并且将知道将实现 ILuisService 的 LuisService 包含到我们的 luis 对话框 MyLuisDialog 中。
您的具体实现可能会有所不同,但此示例将为您提供所需的内容。祝你好运!
创建自定义 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>
{
}