将ConsumeContext注入到作用域对象中

时间:2018-04-09 20:46:30

标签: c# .net masstransit

我正在尝试设置一些范围内的对象并将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();
    }
}

但实际上_contextnull。之所以发生这种情况是因为我在InjectContextFilter创建范围之前触发了ScopeConsumerFactory<TConsumer>,因此,我确实注入了消费者使用的范围。

我的问题是如何在ScopeConsumerFactory<TConsumer>之后应用我的InjectContextFilter?或者如何以任何其他方式将ConsumeContex注入范围对象?

演示代码here

工作演示为here

0 个答案:

没有答案