我正在尝试设置一些范围内的对象并将ConsumeContext
注入其中,以便在实例后期使用它以发送一些消息。
以下是我试图实现它的方式
首先ScopedObject
public class ScopedObject
{
public Guid ScopeId { get; set; } = NewId.NextGuid();
private ConsumeContext _context;
public void SetContext(ConsumeContext context)
{
_context = context;
}
public Task DoSomeStaff()
{
if (_context == null)
throw new NullReferenceException(nameof(_context));
// publish message to bus using _context here...
return Task.CompletedTask;
}
}
然后我准备InjectContextFilter
,只需解析ScopedObject
并将ConsumeContext
注入其中
public class InjectContextFilter : IFilter<ConsumeContext>
{
private IServiceProvider _container;
public InjectContextFilter(IServiceProvider container)
{
_container = container;
}
public async Task Send(ConsumeContext context, IPipe<ConsumeContext> next)
{
try
{
var scoped = _container.GetRequiredService<ScopedObject>();
if (scoped != null)
{
scoped.SetContext(context);
}
await next.Send(context).ConfigureAwait(false);
}
catch (Exception)
{
throw;
}
}
public void Probe(ProbeContext context)
{
var scope = context.CreateFilterScope("cqrslite");
}
}
设置MassTransit
var services = new ServiceCollection();
services.AddScoped<ScopedObject>();
services.AddMassTransit(x =>
{
x.AddConsumer<DoSomeWorkConsumer>();
});
services.AddSingleton(context => Bus.Factory.CreateUsingRabbitMq(x =>
{
IRabbitMqHost host = x.Host(new Uri("rabbitmq://guest:guest@localhost:5672/test"), h => { });
x.ReceiveEndpoint(host, $"receiver_queue", e =>
{
e.UseContextInjection(container);
e.LoadFrom(container);
});
x.UseSerilog();
}));
container = services.BuildServiceProvider();
var busControl = container.GetRequiredService<IBusControl>();
以后在消费者中我希望能够访问ScopedObject
,并希望ConsumeContext
已经注入
public class DoSomeWorkConsumer : IConsumer<DoSomeWork>
{
private ScopedObject _scoped;
public DoSomeWorkConsumer(ScopedObject scoped)
{
_scoped = scoped ?? throw new ArgumentNullException(nameof(scoped));
}
public async Task Consume(ConsumeContext<DoSomeWork> context)
{
await _scoped.DoSomeStaff();
}
}
但实际上_context
是null
。之所以发生这种情况是因为我在InjectContextFilter
创建范围之前触发了ScopeConsumerFactory<TConsumer>
,因此,我确实注入了消费者使用的范围。
我的问题是如何在ScopeConsumerFactory<TConsumer>
之后应用我的InjectContextFilter?或者如何以任何其他方式将ConsumeContex
注入范围对象?
演示代码here
解
工作演示为here