我正在尝试使用Rebus执行请求/回复,但也使用Windsor容器NuGet包:https://github.com/rebus-org/Rebus.CastleWindsor
查看以下样本后:
https://github.com/rebus-org/RebusSamples/tree/master/RequestReply
https://github.com/rebus-org/RebusSamples/tree/master/Integration
我在下面拼凑了这个例子:
public class ContactModule : NancyModule
{
public ContactModule(IBus bus)
{
Get["/v1/contact"] = parameters =>
{
var contacts = new List<Contact>();
using (var activator = new BuiltinHandlerActivator())
{
var settings = new Settings();
activator.Handle<GetContactsResponse>(response =>
{
contacts = response.Contacts;
return Task.FromResult(0);
});
Configure.With(activator)
.Logging(l => l.ColoredConsole(LogLevel.Warn))
.Transport(t => t.UseRabbitMq(
settings.RabbitMQConnectionString,
settings.OutputQueueName)) // we listen for messages in the output queue
.Routing(r => r.TypeBased().MapAssemblyOf<GetContactsRequest>(settings.InputQueueName)) // but we publish to the input queue
.Options(o =>
{
o.EnableCompression();
o.EnableEncryption(settings.MessageEncryptionKey);
})
.Start();
activator.Bus.Publish(new GetContactsRequest``()).Wait();
}
return Response.AsJson(contacts);
};
}
}
我知道在使用Windsor容器方法时它应该看起来更像下面,但我不知道如何听取回复:
public class ContactModule : NancyModule
{
public ContactModule(IBus bus)
{
Get["/v1/contact"] = parameters =>
{
var contacts = new List<Contact>();
bus.Publish(new GetContactsRequest()).Wait();
// How do I listen for the reply?
return Response.AsJson(contacts);
};
}
}
我的留言处理程序:
public class GetContactsHandler : IHandleMessages<GetContactsRequest>
{
private readonly IBus _bus;
private readonly Settings _settings;
public GetContactsHandler(IBus bus, Settings settings)
{
_bus = bus;
_settings = settings;
}
public async Task Handle(GetContactsRequest request)
{
// Fetch contacts from db...
var contacts = new List<Contact>();
await _bus.Reply(new GetContactsResponse {Contacts = contacts});
}
}
My Rebus Windsor安装程序:
public class RebusInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var settings = new Settings();
Configure.With(new CastleWindsorContainerAdapter(container))
.Logging(l => l.ColoredConsole(LogLevel.Warn))
.Transport(t => t.UseRabbitMqAsOneWayClient(
settings.RabbitMQConnectionString))
.Routing(r => r.TypeBased().MapAssemblyOf<GetContactsRequest>(settings.InputQueueName))
.Options(o =>
{
o.EnableCompression();
o.EnableEncryption(settings.MessageEncryptionKey);
})
.Start();
}
}
我面临的问题是我想在我的web api中使用请求/回复模式来请求联系人列表,等待包含检索到的联系人的回复并将其返回给api调用者。
但是如果我想将Windsor容器适配器用于Rebus,IHandlerActivator接口不会公开允许注册内联消息处理程序的.Handle方法,在该方法中,我从回复中抓取联系人,然后将它们发送回api来电。
有没有办法做到这一点,或者我是否错误地解决了这个问题?
编辑:正如您在第一个示例中所看到的,我从Windsor容器中注入IBus接口。 但是,如果我使用注入的总线,我如何告诉它监听从消息处理程序返回的回复?
更新:Rebus.Async正是我所寻找的:https://github.com/rebus-org/Rebus.Async
答案 0 :(得分:2)
当您使用真正的IoC容器时,您应该创建一个实现IHandleMessages<TMessage>
的类,例如像这样:
public class GetContactsRequestHandler : IHandleMessages<GetContactsRequest>
{
readonly IBus _bus;
public GetContactsRequestHandler(IBus bus)
{
_bus = bus;
}
public async Task Handle(GetContactsRequest request)
{
var reply = new GetContactsReply(...);
await _bus.Reply(reply);
}
}
在您添加处理程序并为程序提供应用程序和域服务时,可以更好地扩展。
这当然意味着您必须引入Rebus.CastleWindsor NuGet包并将WindsorContainerAdapter
传递给Rebus&#39; .With(...)
方法。
当您需要在Windsor中注册处理程序时,您可以利用Rebus.CastleWindsor中的扩展方法来执行以下操作:
// register all handler types from this assembly
windsorContainer.AutoRegisterHandlersFromThisAssembly();
// register all handler types from typeof(SomeHandler).Assembly
windsorContainer.AutoRegisterHandlersFromAssemblyOf<SomeHandler>();
// register one particular type as a message handler
windsorContainer.RegisterHandler<GetContactsRequestHandler>();
在您添加更多信息后更新 - 您说:
(...)或我是否错误地接近了这个问题?
我想说&#34;是&#34;,因为服务总线不是很擅长同步请求/回复 - 你应该使用&#34;请求/回复导向&#34;为此,例如HTTP(*)。
另外 - 我对南希几乎一无所知,但我很确定
bus.Publish(...).Wait();
将陷入僵局,至少如果您在ASP.NET中主持Nancy。
你应该总是
await bus.Publish(...);
什么时候可以,在南希,你可以这样做:
Get["/v1/contact"] = async (parameters, ct) =>
{
(...)
await bus.Publish(...);
(...)
};
PS:最后一件事:只要您希望端点处理消息,请记住保持容器。
在您发布的代码中,您在发布活动后立即处置BuiltinHandlerActivator
,这意味着您很可能根本无法处理任何消息。
如果您使用Windsor,当您处理Windsor容器时,将处理公共汽车。
(*)虽然Rebus实际上有Rebus.Async这是一个可以在你的场景中使用的请求/响应API。
我不建议走这条路。如果您打算这样做一次,那么您应该只这样做,然后再也不会这样做:)