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

时间:2019-01-16 15:57:30

标签: c# wpf dependency-injection interface autofac

我目前正在从事一个项目,该项目允许第三方参与我们产品的消息代理。任务是提供这些第三方可以使用的库。我希望能够将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();
}

不应允许供应商发布/发送消息,而应该仅是消耗者。如何隐藏消息的使用方式,以便可以打包服务总线库,而不能公开后台使用的库?

编辑1 使用大众运输消费一条消息

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>();
    }
};

我希望包装器执行的操作是允许开发人员说“使用队列工厂,我想用 this 队列名称构造一个实例,这是实现类型的名称消费者接口隐藏了总线技术的接口。”我只是不知道我是否可以隐藏消费者。

1 个答案:

答案 0 :(得分:0)

如果我的理解正确,那么您希望避免将代码耦合到NServiceBus或MassTransit,并且不想公开正在使用的代码。

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

为了确保避免这种耦合,我将具体的实现保存在单独的项目/库中。您的“核心”域也不应直接引用。如果您可以在没有任何具体实现的情况下对代码进行单元测试,则可以在实现之间自由切换。

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

然后,隐藏使用的实现:
至于不公开使用NServiceBus还是MassTransit,则不能。如果有人引用您的库,并且该库依赖于其中一个软件包,则他们也必须添加该软件包。假设您的库是为NuGet打包的,则该软件包将显示其依赖性。