首页 文章

NServiceBus删除IBus - 利用IPipelineContext和IMessageSession

提问于
浏览
1

我正在将NServiceBus迁移到v6,并且在删除对IBus的引用的过程中遇到了障碍 .

我们为许多应用程序(网站,微服务等)构建了一个公共库,这个库具有IEventPublisher的概念,它本质上是一个发送和发布界面 . 该库不了解NSB . 然后,我们可以使用应用程序中的DI提供此IEventPublisher的实现,这样可以非常轻松地将库的消息传递替换为其他技术 .

所以我们最终得到的是类似的实现

public class NsbEventPublisher : IEventPublisher
{
    IEndpointInstance _instance;

    public NsbEventPublisher(IEndpointInstance endpoint)
    {
        instance = endpoint;
    }

    public void Send(object message)
    {
        instance.Send(message, sendOptions);
    }

    public void Publish(object message)
    {
        instance.Publish(message, sendOptions);
    }
}

这是对实际情况的简化,但说明了我的问题 . 现在当DI容器被要求提供IEventPublisher时,它知道返回一个NsbEventPublisher,它知道解析IEndpointInstance,因为我们将网站的引导程序中的这个绑定到容器作为单例 . 一切都很好,我的网站运行完美 .

我现在正在迁移微服务(在NSB.Host中运行),并且DI容器在解析消息处理程序中的依赖项时拒绝解析IEndpointInstance . 阅读文档这是故意的,我应该在消息处理程序中使用IMessageHandlerContext . https://docs.particular.net/nservicebus/upgrades/5to6/moving-away-from-ibus文档甚至可以避免在MyContextAccessingDependency类的底部示例中遇到的问题 . 建议是通过方法传递消息上下文,该方法对在消息处理程序的上下文中运行的代码进行硬依赖 .

我想要做的是访问发件人/发布者,DI容器可以给我正确的实现 . 代码不需要调用者的任何概念,如果它是从消息处理程序或只想发布的自托管应用程序调用的 .

我看到有两个接口用于与“总线”IPipelineContext和IMessageSession通信,IMessageHandlerContext和IEndpointInstance接口分别扩展 . 我想知道的是,两个接口的统一被NSB绑定到容器中,所以我可以接受发送/发布消息的接口 . 在处理程序中,它是IMessageHandlerContext,在我自己托管的应用程序中是IEndPointInstance .

目前我希望根据应用程序托管来改变我的IEventPublisher实现 . 我只是希望可能会讨论如何在没有可靠的发送/发布接口的情况下对这种方法进行建模,而不管是什么启动了代码路径的执行 .

1 回答

  • 1

    在我到达代码之前需要注意的一些事项:

    • 抽象承诺的抽象,永远不会奏效 . 我从未见过“我将抽象ESB / Messaging / Database / ORM以便我可以在将来交换它”的论点 . 永远 .

    • 当您抽象消息发送功能时,您将丢失库提供的一些功能 . 在这种情况下,您无法执行“对话”或使用会影响您整体体验的“Sagas”,例如:当在ServiceInsight中使用监视工具和观察图表时,您将看不到整个图片,而只看到通过系统的消息的数量 .

    现在,为了完成这项工作,您需要在 endpoints 启动时在容器中注册 IEndpointInstance . 然后,该接口可用于依赖注入,例如在 NsbEventPublisher 中发送消息 .

    像这样的东西(取决于你正在使用哪个IoC容器,这里我假设Autofac):

    static async Task AsyncMain()
    {
        IEndpointInstance endpoint = null;
    
        var builder = new ContainerBuilder();
    
        builder.Register(x => endpoint)
               .As<IEndpointInstance>()
               .SingleInstance();   
    
        //Endpoint configuration goes here...
    
        endpoint = await Endpoint.Start(busConfiguration)
                                 .ConfigureAwait(false);
    }
    

    提到使用IEndpointInstance / IMessageSession的问题here .

相关问题