MassTransit 建议以 IServiceProvider 作为负载提供与容器无关的 Scope Provider
MassTransit suggestion to provide a container agnostic Scope Provider with IServiceProvider as a payload
我在向 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>();
}
}
Microsoft Extensions Dependency Injection 包缺少一些扩展方法,我已添加并随 5.0.2 一起发布。
我在向 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>();
}
}
Microsoft Extensions Dependency Injection 包缺少一些扩展方法,我已添加并随 5.0.2 一起发布。