如何解决“注册为 'Async Scoped' 生活方式,但实例是在活动(异步范围)范围的上下文之外请求的”

How to resolve " registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope"

我正在使用 TopShelf、Quartz 和 SimpleInjector。所以我一直有这个例外,我尝试做混合,但最终得到

"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"

当我不使用 simpleinjector 并在构造函数中不传递接口的情况下简单调用 class 时,它会调用 Start 方法,但如果我使用 simpleinjector,它不会调用指定的 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());
    });
});

这是错误堆栈跟踪:

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](ScopedRegistration1 registration) at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration1 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__01.b__0_0(HostSettings serviceFactory) at Topshelf.Builders.DelegateServiceBuilder1.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(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](ScopedRegistration1 registration) at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration1 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.GetInstanceForRootTypeTService at SimpleInjector.Container.GetInstanceTService at Topshelf.SimpleInjector.ServiceConfiguratorExtensions.<>c__01.<ConstructUsingSimpleInjector>b__0_0(HostSettings serviceFactory) at Topshelf.Builders.DelegateServiceBuilder1.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(Action1 configureCallback) at Topshelf.HostFactory.Run(Action`1 configureCallback)

编辑:我的 simpleinjector 容器包含以下内容:

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);

所以我已经通过阅读以下内容解决了这个问题URL: https://simpleinjector.readthedocs.io/en/latest/decisions.html#don-t-allow-resolving-scoped-instances-outside-an-active-scope

这只是意味着对于特定的一组 classes 使用的生活方式是错误的(例如,您正在强制使用异步范围或其他,但它应该是单例或瞬态的)

事实证明,所有使用或继承 DbContext 的 classes 和使用 HttpClient 的那些都应该使用 "Lifestyle.Singleton" 并且如果它们有任何依赖项(意味着另一个 class 被注入其中) 那么他们也应该使用 Lifestyle.Singleton。

我最终使用了混合体,并将这种生活方式应用于所有其他注入的 classes(除了那些使用单例的)

var lifeStyle = Lifestyle.CreateHybrid(
                 lifestyleSelector: () => HttpContext.Current != null,
                 trueLifestyle: new AsyncScopedLifestyle(),
                 falseLifeStyle: Lifestyle.Transient);

我希望这对以后的其他人有所帮助。