隐藏接口后面的服务总线实现

Hide service bus implementation behind interfaces

我目前正在从事一个允许第 3 方连接到我们产品的消息代理的项目。任务是提供这些第 3 方可以使用的库。我希望能够将 Mass Transit 或 NServiceBus 与其一起打包,但我想将这些细节隐藏在接口后面。

我已经像这样隐藏了服务总线本身...

public class MyServiceBus : IServiceBus {

  private readonly MassTransit.IBus _bus;
  private readonly MassTransit.IBusControl _busControl;

  public PanelSawServiceBus(MassTransit.IBus bus, MassTransit.IBusControl busControl) {
     _bus = bus;
     _busControl = busControl;
  }

  public Task PublishAsync<T>(T message, CancellationToken token = default(CancellationToken)) where T : class =>
     _bus.Publish(message, token);

  public Task SendAsync<T>(T message, CancellationToken token = default(CancellationToken)) where T : class =>
     (_bus as ISendEndpointProvider)?.Send(message, token);

  public Task StartAsync() => _busControl.StartAsync();
  public Task StopAsync() => _busControl.StopAsync();
}

不应允许供应商 publish/send 消息,而应仅用于消费。如何隐藏消息的使用,以便我可以打包服务总线库而不暴露幕后使用的库?

编辑 1 使用 Mass Transit 使用消息看起来像这样

public class MyConsumer : IConsumer<SomeMessage> {
    public Task Consume(ConsumeContext<SomeMessage> ctx) => Task.CompletedTask;
}

在创建服务总线实例的引导过程中,您可以定义您的消费者(Mass Transit 会在收到消息时构建它们)。

var busControl = Bus.Factory.CreateUsingInMemory(config => {
    config.ReceiveEndpoint("queue_name", endpointCfg => {
        endpointCfg.Consumer<MyConsumer>();
    }
};

我希望包装器做的是允许开发人员说 "Using a queue factory I want to construct an instance with this queue name and here are the names of the types that implement the consumer interface that is hiding the bus technology's interfaces." 我只是不知道我是否可以隐藏消费者。

如果我没理解错的话,您想避免将您的代码耦合到 NServiceBus 或 MassTransit,并且您不想公开您使用的是哪一个。

一、解耦:
您已经通过定义自己的 IServiceBus 接口完成了部分工作。只要您的库仅依赖于该接口而不依赖于任何实现,您就不应该耦合到任何一个。

为了确保您避免这种耦合,我将在单独的 projects/libraries 中保留具体的实现。您的 "core" 域不应直接引用任何一个。如果您可以在没有具体实现的情况下对代码进行单元测试,那么您可以自由地在实现之间切换。

发布库时,您可以发布核心库的组成部分以及您选择的接口的实现。

然后,隐藏使用了哪个实现:
至于不暴露你用的是NServiceBus还是MassTransit,不行。如果有人引用您的库并且它依赖于其中一个包,则他们也必须添加该包。假设您的库是为 NuGet 打包的,该包将显示其依赖项。