实现IBotToUser翻译后Bot消息无法写入Table Storage问题
嘿,我明白你的问题了——当你注册了自定义的翻译拦截类后,Bot发送的消息就没法存到Table Storage的Activities表了,但禁用翻译又能正常记录。这其实是因为你的DI注册直接替换了Bot Framework默认的IBotToUser实现,而默认实现恰恰包含了把消息写入活动表的逻辑。
问题根源
Bot Framework自带的BotToUser类(默认的IBotToUser实现)内部会处理活动记录到Table Storage的逻辑。但你现在的DI注册用自己的InterceptBotToUserTranslator完全替换了这个默认实现,导致记录活动的代码根本没机会运行。
解决方案:用装饰器模式包装原始实现
正确的做法是用装饰器模式,让你的翻译类"包裹"住原始的IBotToUser实现,这样既能执行翻译逻辑,又不会丢失原本的活动记录功能。
第一步:修改DI注册代码
把你原来的DI注册改成这样:
// 先注册Bot Framework默认的IBotToUser实现 Builder.RegisterType<BotToUser>().As<IBotToUser>().InstancePerLifetimeScope(); // 注册你的拦截类(如果确实需要保留的话) Builder.RegisterType<InterceptBotToUser>().AsSelf().InstancePerLifetimeScope(); // 关键:用装饰器模式注册翻译类,让它注入原始的IBotToUser Builder.RegisterDecorator<InterceptBotToUserTranslator, IBotToUser>() .InstancePerLifetimeScope();
第二步:优化翻译类(可选)
其实你的InterceptBotToUser类看起来和默认的BotToUser功能重复了,你可以简化代码,直接让翻译类依赖原始的IBotToUser,这样不需要额外的InterceptBotToUser:
public class InterceptBotToUserTranslator : IBotToUser { private readonly IBotToUser _innerBotToUser; // 如果有翻译服务,这里可以注入 // private readonly IMyTranslationService _translationService; public InterceptBotToUserTranslator(IBotToUser innerBotToUser/*, IMyTranslationService translationService*/) { SetField.NotNull(out _innerBotToUser, nameof(innerBotToUser), innerBotToUser); // SetField.NotNull(out _translationService, nameof(translationService), translationService); } public IMessageActivity MakeMessage() { // 直接调用原始实现的方法 return _innerBotToUser.MakeMessage(); } public async Task PostAsync(IMessageActivity message, CancellationToken cancellationToken = default) { // 在这里执行翻译逻辑 // message.Text = await _translationService.TranslateTextAsync(message.Text, "目标语言代码"); // 调用原始的PostAsync,这样默认的活动记录逻辑会被触发 await _innerBotToUser.PostAsync(message, cancellationToken); } }
为什么这样能解决问题?
用RegisterDecorator注册后,当请求IBotToUser实例时,Autofac(假设你用的是Autofac)会先创建原始的BotToUser实例,再把它注入到你的InterceptBotToUserTranslator中。这样你的翻译逻辑执行完后,会调用原始实例的PostAsync方法,而原始方法里就包含了把消息写入Table Storage的逻辑。
验证效果
修改完之后,再测试一下:
- Bot发送的消息应该正常翻译并推送给用户
- 同时,这条消息会被自动记录到Table Storage的Activities表中
内容的提问来源于stack exchange,提问作者GeekzSG

