I am using TopShelf, Quartz and SimpleInjector. So I keep having this exception, I tried doing hybrid, but ended up with
"is registered as 'Hybrid Async Scoped / Web Request' lifestyle, but the instance is requested outside the context of an active (Hybrid Async Scoped / Web Request) scope"
When I don't use the simpleinjector and simple call the class without passing interfaces in the constructor, it calls the Start method, but if I do use the simpleinjector it doesn't call the specified FooService:
HostFactory.Run(config =>
{
config.SetServiceName("Foo Scheduler");
config.SetDisplayName("Foo Scheduler");
config.RunAsLocalSystem();
config.UseSimpleInjector(container);
config.StartAutomatically();
config.Service<IFooService>(scheduler =>
{
scheduler.ConstructUsingSimpleInjector();
scheduler.WhenStarted((s, c) => s.Start());
scheduler.WhenStopped((s, c) => s.Stop());
});
});
Here is the error stack trace:
Topshelf v4.2.1.215, .NET Framework v4.0.30319.42000 Topshelf.HostFactory Error: 0 : An exception occurred creating the host, Topshelf.ServiceBuilderException: An exception occurred creating the service: IFooService ---> SimpleInjector.ActivationException: FooService is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope. Please see https://simpleinjector.org/scoped for more information about how to manage scopes. at SimpleInjector.Scope.GetScopelessInstance[TImplementation](ScopedRegistration
1 registration) at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration
1 registration, Scope scope) at SimpleInjector.Advanced.Internal.LazyScopedRegistration1.GetInstance(Scope scope) at lambda_method(Closure ) at SimpleInjector.InstanceProducer.GetInstance() at SimpleInjector.Container.GetInstanceFromProducer(InstanceProducer instanceProducer, Type serviceType) at SimpleInjector.Container.GetInstanceForRootType[TService]() at SimpleInjector.Container.GetInstance[TService]() at Topshelf.SimpleInjector.ServiceConfiguratorExtensions.<>c__0
1.b__0_0(HostSettings serviceFactory) at Topshelf.Builders.DelegateServiceBuilder1.Build(HostSettings settings) --- End of inner exception stack trace --- at Topshelf.Builders.DelegateServiceBuilder
1.Build(HostSettings settings) at Topshelf.Builders.RunBuilder.Build(ServiceBuilder serviceBuilder) at Topshelf.HostConfigurators.HostConfiguratorImpl.CreateHost() at Topshelf.HostFactory.New(Action1 configureCallback) Topshelf.HostFactory Error: 0 : The service terminated abnormally, Topshelf.ServiceBuilderException: An exception occurred creating the service: IFooService ---> SimpleInjector.ActivationException: FooService is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope. Please see https://simpleinjector.org/scoped for more information about how to manage scopes. at SimpleInjector.Scope.GetScopelessInstance[TImplementation](ScopedRegistration
1 registration) at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration1 registration, Scope scope) at SimpleInjector.Advanced.Internal.LazyScopedRegistration
1.GetInstance(Scope scope) at lambda_method(Closure ) at SimpleInjector.InstanceProducer.GetInstance() at SimpleInjector.Container.GetInstanceFromProducer(InstanceProducer instanceProducer, Type serviceType) at SimpleInjector.Container.GetInstanceForRootTypeTService at SimpleInjector.Container.GetInstanceTService at Topshelf.SimpleInjector.ServiceConfiguratorExtensions.<>c__01.<ConstructUsingSimpleInjector>b__0_0(HostSettings serviceFactory) at Topshelf.Builders.DelegateServiceBuilder
1.Build(HostSettings settings) --- End of inner exception stack trace --- at Topshelf.Builders.DelegateServiceBuilder1.Build(HostSettings settings) at Topshelf.Builders.RunBuilder.Build(ServiceBuilder serviceBuilder) at Topshelf.HostConfigurators.HostConfiguratorImpl.CreateHost() at Topshelf.HostFactory.New(Action
1 configureCallback) at Topshelf.HostFactory.Run(Action`1 configureCallback)
EDIT: My simpleinjector container contains the following:
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
container.RegisterInstance<IJobFactory>(new SimpleInjectorJobFactory(container));
var quartzSchedulerFactory = new StdSchedulerFactory();
container.RegisterInstance<ISchedulerFactory>(quartzSchedulerFactory);
container.RegisterInstance<IScheduler>(await quartzSchedulerFactory.GetScheduler());
container.Register<IJobListener, CtrackJobListener>(Lifestyle.Scoped);
container.Register<ISchedulerService, SchedulerService>(Lifestyle.Scoped);
So I already solved the answer by reading the following URL: https://simpleinjector.readthedocs.io/en/latest/decisions.html#don-t-allow-resolving-scoped-instances-outside-an-active-scope
It just meant that the lifestyle being used is wrong for particular set of classes (for example you are forcing async scope or other, but it should have been a singleton or transient)
It turns out that all classes using or inheriting DbContext and those that use HttpClient should use "Lifestyle.Singleton" and if they have any dependencies (meaning another class was injected in them) then they should use a Lifestyle.Singleton as well.
I ended up using a hybrid, and applied this lifestyle to ALL the other injected classes (except for those using singletons)
var lifeStyle = Lifestyle.CreateHybrid(
lifestyleSelector: () => HttpContext.Current != null,
trueLifestyle: new AsyncScopedLifestyle(),
falseLifeStyle: Lifestyle.Transient);
I hope this may help someone else in the future.