You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:02:16