C# 如何基于数据库动态表配置的值触发对应问卷业务方法
可行实现思路
方案1:策略模式 + 类名映射(完全匹配你的需求)
- 步骤1:抽象统一的回复处理接口
定义所有回复逻辑的公共执行规范,示例:
每个独立的回复逻辑单独实现该接口,比如取消预约场景的Yes逻辑:public interface IQuestionReplyHandler { // 统一执行方法,Context封装所有需要的参数:会话信息、用户回复、关键词配置等 Task ExecuteAsync(ReplyHandleContext context); }
对应的No逻辑、跳转下一题等其他逻辑,都单独写对应的实现类即可。public class CancelAppointmentYesHandler : IQuestionReplyHandler { // 可以通过构造函数注入你需要的Repo、服务等依赖 private readonly IMessageRepo _messageRepo; public CancelAppointmentYesHandler(IMessageRepo messageRepo) { _messageRepo = messageRepo; } public async Task ExecuteAsync(ReplyHandleContext context) { // 这里写原来if(templateKeyword.Keyword == "yes")里的逻辑:校验、插数据等 } } - 步骤2:数据库新增配置字段
在你的关键词关联表中新增handler_class_name字段,存储对应逻辑实现类的全称,比如Yes关键词对应的记录就填你的命名空间.CancelAppointmentYesHandler。 - 步骤3:实现动态映射调用
程序启动时扫描所有实现了IQuestionReplyHandler接口的类,存入全局字典(Key为类全称,Value为类的实例/构造委托),或者直接通过依赖注入容器托管所有Handler实例。用户回复时的逻辑简化为:templateKeyword = _messageRepo.GetMessageTemplateKeyword(conversation.CurrentTemplateId.Value, messageReceived); if (templateKeyword != null && templateKeyword.ReplyTemplateId > 0) { // 直接从字典/DI容器中取出对应的处理器 var handler = _handlerFactory.GetHandler(templateKeyword.HandlerClassName); // 执行逻辑,完全不需要if判断关键词 await handler.ExecuteAsync(new ReplyHandleContext(conversation, messageReceived, templateKeyword)); } - 安全优化:新增白名单校验,只允许加载你指定Handler目录下的类,避免数据库被篡改后执行非预期逻辑。
方案2:枚举映射(更安全,耦合度低)
如果你担心存类名容易和代码强绑定,可以把字段换成handler_type枚举,枚举值对应所有的处理逻辑类型,然后写个工厂类根据枚举值返回对应的Handler实例,新增逻辑时只需要加枚举项、加对应的Handler实现、修改工厂映射即可,依然不需要修改核心的回复处理流程。
扩展优化
如果部分逻辑需要自定义参数,比如跳转下一题的逻辑需要指定下一题的ID,可以在数据库再新增handler_params字段,存储JSON格式的参数,执行时反序列化后传给Handler即可,完全可以做到新增通用逻辑无需修改代码,纯配置即可上线。
内容的提问来源于stack exchange,提问作者VAAA
相关产品推荐
相关产品推荐

