Closed sabbadino closed 4 years ago
The thing is, Rebus does NOT use IoC for any of its things at runtime.
It uses Injectionist to compose itself from the configuration you choose, which allows you to hook into it in various ways by decorating services, and then it may use IoC to create your handlers if you provided some kind of container adapter.
But the pipelines are constructed by Injectionist when the bus instance is created, and so it is not possible to resolve the steps from your container.
However, it's certainly possible to write a pipeline step that resolves stuff from your container. If you're using Rebus.ServiceProvider, the current scope will be added to the context when your handler(s) have been resolved, so if you add a step like this:
Configure.With(...)
.(...)
.Options(o => {
// (*)
o.Decorate<IPipeline>(c => {
var pipeline = c.Get<IPipeline>();
var step = new MyStep();
return new PipelineStepInjector(pipeline)
.OnReceive(step, PipelineRelativePosition.After, typeof(ActivateHandlersStep));
});
})
.Start();
(positioning your step af Rebus' own ActivateHandlersStep
), then your step can get access to the scope like this:
public class MyStep : IIncomingStep
{
public async Task Process(IncomingStepContext context, Func<Task> next)
{
var scope = context.Load<IServiceScope>();
// whee!
await next();
}
}
(*) Please always hide the nasty .Decorate(...)
stuff behind an extension method so it becomes pretty like this:
Configure.With(...)
.(...)
.Options(o => o.UseMyStep())
.Start();
EDIT: Just corrected the first snippet to use ActivateHandlersStep
for positioning. Check out this test for a working sample.
@mookid8000 I tried the following configuration
services.AddRebus(configure =>
{
return configure
.Transport(t => t.UseAzureServiceBus(connectionString, serviceQueueName))
.Options(o =>
{
o.Decorate<IPipeline>(c => {
var pipeline = c.Get<IPipeline>();
var step = new MyStep();
return new PipelineStepInjector(pipeline)
.OnReceive(step, PipelineRelativePosition.After, typeof(DependencyInjectionHandlerActivator));
});
});
});
But it fails with
Rebus.Injection.ResolutionException: Could not resolve Rebus.Pipeline.IPipeline with decorator depth 0 - registrations:
Rebus.Injection.Injectionist+Handler ---> System.ArgumentException:
Could not finish composition of the RECEIVE pipeline because the following injections could not be made:
<customnamespace>.Management.Api.MyStep => After => Rebus.ServiceProvider.DependencyInjectionHandlerActivator
Please pick other steps to use when anchoring your step injections, or pick another way of assembling the pipeline.
If you require the ultimate flexibility, you will probably need to decorate IPipeline and compose it manually.
at Rebus.Pipeline.PipelineStepInjector.ComposeReceivePipeline()+MoveNext()
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Rebus.Pipeline.PipelineStepConcatenator.ReceivePipeline() in C:\\projects-rebus\\Rebus\\Rebus\\Pipeline\\PipelineStepConcatenator.cs:line 78
at Rebus.Pipeline.PipelineCache..ctor(IPipeline pipeline) in C:\\projects-rebus\\Rebus\\Rebus\\Pipeline\\PipelineCache.cs:line 14
at Rebus.Config.RebusConfigurer.<>c.<Start>b__13_22(IResolutionContext c) in C:\\projects-rebus\\Rebus\\Rebus\\Config\\RebusConfigurer.cs:line 356
at Rebus.Injection.Injectionist.ResolutionContext.Get[TService]() in C:\\projects-rebus\\Rebus\\Rebus\\Injection\\Injectionist.cs:line 199
--- End of inner exception stack trace ---
at Rebus.Injection.Injectionist.ResolutionContext.Get[TService]() in C:\\projects-rebus\\Rebus\\Rebus\\Injection\\Injectionist.cs:line 248
at Rebus.Config.RebusConfigurer.<>c.<Start>b__13_11(IResolutionContext c) in C:\\projects-rebus\\Rebus\\Rebus\\Config\\RebusConfigurer.cs:line 232
at Rebus.Injection.Injectionist.ResolutionContext.Get[TService]() in C:\\projects-rebus\\Rebus\\Rebus\\Injection\\Injectionist.cs:line 199
at Rebus.Config.RebusConfigurer.<>c.<Start>b__13_13(IResolutionContext c) in C:\\projects-rebus\\Rebus\\Rebus\\Config\\RebusConfigurer.cs:line 254
at Rebus.Injection.Injectionist.ResolutionContext.Get[TService]() in C:\\projects-rebus\\Rebus\\Rebus\\Injection\\Injectionist.cs:line 199
at Rebus.Config.RebusConfigurer.<>c__DisplayClass13_0.<Start>b__27(IResolutionContext c) in C:\\projects-rebus\\Rebus\\Rebus\\Config\\RebusConfigurer.cs:line 369
at Rebus.Injection.Injectionist.ResolutionContext.Get[TService]() in C:\\projects-rebus\\Rebus\\Rebus\\Injection\\Injectionist.cs:line 199
at Rebus.Config.RebusConfigurer.<>c__DisplayClass13_0.<Start>b__28(IResolutionContext c) in C:\\projects-rebus\\Rebus\\Rebus\\Config\\RebusConfigurer.cs:line 390
at Rebus.Injection.Injectionist.ResolutionContext.Get[TService]() in C:\\projects-rebus\\Rebus\\Rebus\\Injection\\Injectionist.cs:line 199
at Rebus.Injection.Injectionist.Get[TService]() in C:\\projects-rebus\\Rebus\\Rebus\\Injection\\Injectionist.cs:line 57
at Rebus.Config.RebusConfigurer.Start() in C:\\projects-rebus\\Rebus\\Rebus\\Config\\RebusConfigurer.cs:line 436
at Rebus.Config.DelayedStartupConfigurationExtensions.Create(RebusConfigurer configurer) in C:\\projects-rebus\\Rebus\\Rebus\\Config\\DelayedStartupConfigurationExtensions.cs:line 19
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitSingleton(SingletonCallSite singletonCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Rebus.ServiceProvider.ServiceCollectionExtensions.<>c.<AddRebus>b__1_5(IServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitSingleton(SingletonCallSite singletonCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Rebus.ServiceProvider.ServiceCollectionExtensions.<>c.<AddRebus>b__1_6(IServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitSingleton(SingletonCallSite singletonCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Rebus.ServiceProvider.ServiceProviderExtensions.UseRebus(IServiceProvider provider, Action`1 busAction)
at <customnamespace>.Management.Api.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env) in <customproject>\\Startup.cs:line 169
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
at Microsoft.ApplicationInsights.AspNetCore.ApplicationInsightsStartupFilter.<>c__DisplayClass2_0.<Configure>b__0(IApplicationBuilder app)
at Microsoft.AspNetCore.Mvc.Internal.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder)
at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()","Properties":{"EventId":{"Id":6},"SourceContext":"Microsoft.AspNetCore.Hosting.Internal.WebHost"
Hi, according to the post of @slimjack , shouldn't you re open the topic ? Or a new one must opened ?
hi @slimjack , sorry for taking so long to get back to you ... and no need to reopen.... I'll get back to you on Tuesday 🙂
Hi again @slimjack , sorry, but the exception you get there is because I was a little bit too fast when I posted the code snippets above! I've corrected the snippets to work.
The reason it didn't work is because DependencyInjectionHandlerActivator
is not a step, it's a service, which Rebus uses from its built-in ActivateHandlersStep
– so we simply need to position our step AFTER the ActivateHandlersStep
, which is done like this:
.OnReceive(step, PipelineRelativePosition.After, typeof(ActivateHandlersStep));
If you want to see a working example (including wrapping in an extension method), check out this test: https://github.com/rebus-org/Rebus.ServiceProvider/blob/master/Rebus.ServiceProvider.Tests/CheckServiceScopeAccessFromPipelineStep.cs
Hi, I read this wiki page describing how to inject a custom step in the incoming / outgoing pipeline https://github.com/rebus-org/Rebus/wiki/Extensibility
It's no clear to me how to use ioc in this situation : the example provided requires to give a instance of my custom step , while i would like to provide an interface that is resolved by the ioc at run time.
Is it possible ? can you provide an example ? thank you p.s. : using Rebus on dotnertcore 2.2