我正在将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实现。我只是希望可能会讨论如何在没有可靠的发送/发布接口的情况下对这种方法进行建模,而不管是什么启动了代码路径的执行。
答案 0 :(得分:1)
在我到达代码之前需要注意的一些事项:
抽象承诺的抽象,永远不会奏效。我从未见过"我将抽象ESB / Messaging / Database / ORM的论点,以便我可以在将来交换它#34;工作。如初。
当您抽象消息发送功能时,您将丢失该库提供的一些功能。在这种情况下,您无法执行对话'或使用' Sagas'这将妨碍您的整体体验,例如:在ServiceInsight中使用监控工具和观察图表时,您不会看到整个图片,只会看到通过系统的消息。
现在,为了完成这项工作,您需要在端点启动时在容器中注册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。