我有两个通过RabbitMQ进行通信的服务,我想为每个收到的消息应用一个范围生存期。
我的消费者:
public class Consumer
{
private IModel channel;
public Consumer(IModel channel)
{
this.channel = channel;
}
public void Consume()
{
var queue = channel.QueueDeclare(queue: MessagingConfigs.QueueName,
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, args) => HandleMessageReceived(model, args);
channel.BasicConsume(queue: MessagingConfigs.QueueName, autoAck: false, consumer: consumer);
}
private async Task HandleMessageReceived(object model, BasicDeliverEventArgs args)
{
//do logic
}
}
每次触发Received事件时都会调用HandleMessageReceived,每次调用HandleMessageReceived时如何打开新范围?
在线找到解决方案:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IMyScopedService, MyScopedService>();
var serviceProvider = services.BuildServiceProvider();
var serviceScopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
IMyScopedService scopedOne;
using (var scope = serviceScopeFactory.CreateScope())
{
scopedOne = scope.ServiceProvider.GetService<Consumer>();
Consumer.Consume();
}
}
我想如果我在startup.cs中使用上面的内容,那么将在应用程序生命周期中调用一次,并且scope将被打开一次,以下内容可能会有效:
private async Task HandleMessageReceived(object model, BasicDeliverEventArgs args)
{ using (var scope = serviceScopeFactory.CreateScope())
{
//do logic
}
}
但我不想在我的消费者代码中包含生命周期注册,.Net核心是否有办法在每次调用方法时自动打开一个范围,我可以在startup.cs中使用或者的Program.cs?
我的应用程序是.net核心控制台应用程序而不是ASP.NET
答案 0 :(得分:1)
为什么不在附件中包装方法?
首先,为方法创建包装器:
public static class ScopeFactoryExtension
{
public static EventHandler<BasicDeliverEventArgs> WrapInScope(this IServiceScopeFactory scopeFactory, Func<IMyScopedService, object, BasicDeliverEventArgs, Task> func)
{
async void InScope(object arg1, BasicDeliverEventArgs arg2)
{
using (var scope = scopeFactory.CreateScope())
{
await func(scope, arg1, arg2);
}
}
return InScope;
}
}
然后包装整个方法:
consumer.Received += scopeFactory.WrapInScope(HandleMessageReceived);
还需要扩展方法:
private async Task HandleMessageReceived(IMyScopedService service, object model, BasicDeliverEventArgs args)
{
//do logic with service
}