SimpleInjector:如何为多个接口一次性注册代理类
问题描述
我正在开发一个Telegram Bot,使用SimpleInjector进行依赖注入时遇到了注册问题。我需要将ProxyBotMessageSender类注册为BotMessageSender的代理,后者实现了IMessageSender、IMessageForwarder、IMessageCopier三个接口。
代码结构
接口定义
// 发送新消息 public interface IMessageSender{ IObservable<Message> ObservableSend(SendMessage message); IObservable<Message> ObservableSend(MessageBuilder messageBuilder); } // 转发已有消息 public interface IMessageForwarder{ IObservable<Message> Forward(ForwardMessage message); IObservable<MessageIdObject[]> Forward(ForwardMessages messages); } // 复制已有消息 public interface IMessageCopier{ IObservable<MessageIdObject> Copy(CopyMessage message); IObservable<MessageIdObject[]> Copy(CopyMessages messages); }
实现类与代理类
// 第三方库包装类 public class BotMessageSender : IMessageSender, IMessageForwarder, IMessageCopier{ public BotMessageSender(TelegramBot bot) { this.bot = bot; } // 接口实现代码... } // 处理发送限制的代理类,实现IDisposable public class ProxyBotMessageSender : AbstractBotMessageSender, IMessageSender, IMessageForwarder, IMessageCopier, IDisposable{ public ProxyBotMessageSender(IMessageSender sender, IMessageCopier messageCopier, IMessageForwarder messageForwarder) { this.sender = sender; this.messageCopier = messageCopier; this.messageForwarder = messageForwarder; // 其他初始化代码... } // 接口实现与Dispose逻辑... }
当前注册代码
public override void Install() { Container.Register<IMessageSender,BotMessageSender>(Lifestyle.Singleton); Container.Register<IMessageForwarder,BotMessageSender>(Lifestyle.Singleton); Container.Register<IMessageCopier,BotMessageSender>(Lifestyle.Singleton); Container.RegisterDecorator<IMessageSender,ProxyBotMessageSender>(Lifestyle.Singleton); Container.RegisterDecorator<IMessageForwarder,ProxyBotMessageSender>(Lifestyle.Singleton); Container.RegisterDecorator<IMessageCopier,ProxyBotMessageSender>(Lifestyle.Singleton); // 其他注册代码... }
问题在于,当前的注册方式会为每个接口分别创建一个ProxyBotMessageSender实例,但我需要的是同一个代理实例同时作为这三个接口的装饰器,就像手动创建的逻辑一样:
void Method(){ var telegramBot = new TelegramBot(); var sender = new BotMessageSender(telegramBot); var generalSender = new ProxyBotMessageSender(sender, sender, sender); IMessageSender messageSender = generalSender; IMessageCopier messageCopier = generalSender; IMessageForwarder messageForwarder = generalSender; }
如何在SimpleInjector中实现这种注册,同时不违反依赖注入原则?
解决方案
要实现单个ProxyBotMessageSender实例同时装饰三个接口,需要先注册单例代理实例,再将该实例映射到三个接口上,替代原有的装饰器注册方式,具体步骤如下:
方案一:手动创建并注册代理实例
public override void Install() { // 1. 注册原始实现类为单例 Container.Register<IMessageSender, BotMessageSender>(Lifestyle.Singleton); Container.Register<IMessageForwarder, BotMessageSender>(Lifestyle.Singleton); Container.Register<IMessageCopier, BotMessageSender>(Lifestyle.Singleton); // 2. 解析原始实例,创建单例代理 var botSender = Container.GetInstance<BotMessageSender>(); var proxy = new ProxyBotMessageSender(botSender, botSender, botSender); Container.RegisterInstance<ProxyBotMessageSender>(proxy, Lifestyle.Singleton); // 3. 将三个接口的注册替换为同一个代理实例 Container.RegisterInstance<IMessageSender>(proxy); Container.RegisterInstance<IMessageForwarder>(proxy); Container.RegisterInstance<IMessageCopier>(proxy); // 其他注册代码... }
方案二:利用SimpleInjector的条件注册(更符合框架风格)
如果不想手动解析实例,可以通过RegisterConditional确保代理实例唯一:
public override void Install() { // 注册原始实现类为单例 Container.Register<BotMessageSender>(Lifestyle.Singleton); Container.Register<IMessageSender>(() => Container.GetInstance<BotMessageSender>(), Lifestyle.Singleton); Container.Register<IMessageForwarder>(() => Container.GetInstance<BotMessageSender>(), Lifestyle.Singleton); Container.Register<IMessageCopier>(() => Container.GetInstance<BotMessageSender>(), Lifestyle.Singleton); // 注册单例代理 Container.Register<ProxyBotMessageSender>(() => new ProxyBotMessageSender( Container.GetInstance<IMessageSender>(), Container.GetInstance<IMessageCopier>(), Container.GetInstance<IMessageForwarder>() ), Lifestyle.Singleton); // 替换三个接口的注册为同一个代理实例 Container.RegisterConditional<IMessageSender>( c => c.GetInstance<ProxyBotMessageSender>(), Lifestyle.Singleton, _ => true); Container.RegisterConditional<IMessageForwarder>( c => c.GetInstance<ProxyBotMessageSender>(), Lifestyle.Singleton, _ => true); Container.RegisterConditional<IMessageCopier>( c => c.GetInstance<ProxyBotMessageSender>(), Lifestyle.Singleton, _ => true); }
注意事项
- 由于
ProxyBotMessageSender实现了IDisposable,SimpleInjector会自动管理其生命周期,单例模式下会在容器释放时调用Dispose,无需手动处理。 - 两种方案都确保了三个接口注入的是同一个代理实例,符合手动创建的逻辑,同时遵循依赖注入的单一职责和依赖倒置原则。
内容的提问来源于stack exchange,提问作者HedgehogNSK
相关产品推荐
相关产品推荐

