MassTransit建议提供与IServiceProvider作为有效载荷的容器无关的Scope Provider

时间:2018-04-28 21:24:11

标签: masstransit

我在向MassTransit回购提交问题之前在这里提出这个问题......

目前,有许多MassTransit容器扩展提供范围提供程序的实现,这些提供程序将容器特定接口添加到ConsumeContext的有效内容。

例如:

  • AutofacConsumerScopeProvider
    • 有效负载类型:Autofac.ILifetimeScope
  • DependencyInjectionConsumerScopeProvider
    • 有效负载类型:Microsoft.Extensions.DependencyInjection.IServiceScope
  • StructureMapConsumerScopeProvider
    • 有效负载类型:StructureMap.IContainer
  • 等...

如果所有这些扩展都将IServiceProvider添加到上下文有效负载而不是它们的容器特定接口,那么下游消费者可能会将自己与容器框架分离,那会不会更好?

现在,我们必须使用以下逻辑来访问基础IServiceProvider

interface IWidgetService
{
    Task DoSomethingAsync();
}

class WidgetService : IWidgetService
{
    public Task DoSomethingAsync()
    {
        throw new NotImplementedException();
    }
}

private static void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IWidgetService, WidgetService>();

    services.AddTransient<IConsumerScopeProvider, DependencyInjectionConsumerScopeProvider>();
    services.AddTransient(typeof(IConsumerFactory<>), typeof(ScopeConsumerFactory<>));
}

private static IBusControl CreateBus(IServiceProvider serviceProviderRoot)
{
    var busControl = Bus.Factory.CreateUsingRabbitMq(bus =>
    {
        var host = bus.Host("127.0.0.1", "/", configurator =>
        {
            configurator.Username("guest");
            configurator.Password("guest");
        });

        bus.ReceiveEndpoint(host, "test-queue", configurator =>
        {
            configurator.UseExecuteAsync(async context =>
            {
                var consumerScopeProvider = serviceProviderRoot.GetRequiredService<IConsumerScopeProvider>();
                using (var scope = consumerScopeProvider.GetScope(context))
                {
                    // this next line of code is where we must access the payload
                    // using a container specific interface to get access to the
                    // scoped IServiceProvider
                    var serviceScope = scope.Context.GetPayload<IServiceScope>();
                    var serviceProviderScoped = serviceScope.ServiceProvider;

                    var widgetService = serviceProviderScoped.GetRequiredService<IWidgetService>();

                    await widgetService.DoSomethingAsync().ConfigureAwait(false);
                }
            });

            // additional receive endpoint configuration...
        });
    });

    return busControl;
}

此外,我不确定这是否是一个错误,但是DependencyInjectionStateMachineActivityFactory的当前实现是否总是会抛出异常,因为当前没有任何内容将IServiceProvider添加到有效负载上下文中?

public class DependencyInjectionStateMachineActivityFactory :
    IStateMachineActivityFactory
{
    public Activity<TInstance, TData> GetActivity<TActivity, TInstance, TData>(BehaviorContext<TInstance, TData> context)
        where TActivity : Activity<TInstance, TData>
    {
        // this next line will always fail, correct?
        var serviceProvider = context.GetPayload<IServiceProvider>();

        return serviceProvider.GetRequiredService<TActivity>();
    }

    public Activity<TInstance> GetActivity<TActivity, TInstance>(BehaviorContext<TInstance> context) where TActivity : Activity<TInstance>
    {
        // this next line will always fail, correct?
        var serviceProvider = context.GetPayload<IServiceProvider>();

        return serviceProvider.GetRequiredService<TActivity>();
    }
}

1 个答案:

答案 0 :(得分:1)

Microsoft Extensions Dependency Injection软件包有一些缺少的扩展方法,我已添加并随5.0.2一起发布。