具有Hangfire抛出异常的Autofac作业激活器DependencyResolutionException

时间:2015-07-07 10:22:59

标签: asp.net-web-api2 autofac hangfire autofac-module hangfire.ninject

我的项目结构与:

相同

https://github.com/MarlabsInc/webapi-angularjs-spa

我已按照以下说明操作:

http://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html

所以我创建了一个容器作业激活器。

在我的Bootstrapper.cs

containerBuilder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().AsImplementedInterfaces().InstancePerApiRequest();
containerBuilder.RegisterType<UnitOfWork>().As<IUnitOfWork>().AsImplementedInterfaces().InstancePerApiRequest();
containerBuilder.RegisterApiControllers(System.Reflection.Assembly.GetExecutingAssembly());
IContainer container = containerBuilder.Build();

Hangfire.GlobalConfiguration.Configuration
.UseAutofacActivator(container);
JobActivator.Current = new AutofacJobActivator(container);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);

我的启动类有一个方法:

GlobalConfiguration.Configuration
.UseSqlServerStorage("entitiesDB",
new SqlServerStorageOptions
{
    PrepareSchemaIfNecessary = false,
    InvisibilityTimeout = TimeSpan.FromMinutes(30)
});

app.UseHangfireDashboard();
app.UseHangfireServer();

在控制器中:我正在尝试将2000发票的状态更新为&#34;已批准&#34; 所以这个方法很简单如下:

foreach(int id in invoiceIds)
{
   BackgroundJob.Enqueue<IInvoiceService>(a => a.UpdateInvoice(id));
}

现在我在SQL中查询:

 select * from HangFire.[State]

我在数据列中收到以下异常:

  

{&#34; FailedAt&#34;:&#34; 2015-07-07T10:00:40.9454943Z&#34;&#34; ExceptionType&#34;:&#34; Autofac.Core.DependencyResolutionException&# 34;,&#34; ExceptionMessage&#34;:&#34;否   带有标记匹配的范围&#39; AutofacWebRequest&#39;是可见的   请求实例的范围。这通常表明   正在请求按照HTTP请求注册的组件   一个SingleInstance()组件(或类似的场景。)在网络下   集成始终请求来自的依赖项   DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime,   从来没有从容器   。本身&#34;&#34; ExceptionDetails&#34;:&#34; Autofac.Core.DependencyResolutionException:   没有标记匹配的范围&#39; AutofacWebRequest&#39;是可见的   请求实例的范围。这通常表明   正在请求按照HTTP请求注册的组件   一个SingleInstance()组件(或类似的场景。)在网络下   集成始终请求来自的依赖项   DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime,   从来没有从容器本身。\ r \ n at   Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope   mostNestedVisibleScope)\ r \ n at   Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration   注册,IResolveOperation上下文,ISharingLifetimeScope   mostNestedVisibleScope,IEnumerable 1 parameters)\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable 1个参数)\ r \ n at   Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration   注册,IEnumerable 1 parameters)\r\n at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable 1个参数)\ r \ n at   Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration   注册,IEnumerable 1 parameters)\r\n at Autofac.Core.Container.ResolveComponent(IComponentRegistration registration, IEnumerable 1个参数)\ r \ n at   Autofac.ResolutionExtensions.TryResolveService(IComponentContext   context,Service service,IEnumerable 1 parameters, Object& instance)\r\n at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable 1个参数)\ r \ n at   Autofac.ResolutionExtensions.Resolve(IComponentContext context,Type   serviceType,IEnumerable`1参数)\ r \ n at   Autofac.ResolutionExtensions.Resolve(IComponentContext context,Type   service.)\ r \ n在Hangfire.AutofacJobActivator.ActivateJob(类型   jobType)\ r \ n在Hangfire.Common.Job.Activate(JobActivator   活化剂)&#34;}

有人可以帮我理解我做错了吗?

1 个答案:

答案 0 :(得分:2)

您正在使用InstancePerApiRequest,因此您的IoC容器知道为每个API请求创建新实例。

但是,您的后台作业未在API请求中执行,因此您的IoC容器不知道如何解决您的依赖项。

来自hangfire docs

  

HttpContext不可用

     

在实例化目标类型期间,请求信息不可用。如果在请求范围中注册依赖项(Autofac中的InstancePerHttpRequest,Ninject中的InRequestScope等),则在作业激活过程中将抛出异常。

     

因此,整个依赖图应该可用。在不使用请求范围的情况下注册其他服务,或者如果您的IoC容器不支持多个范围的依赖注册,则使用单独的容器实例。

根据this related SO question,Autofac不支持注册多个范围,因此您需要:

  1. 使用“较低”范围,例如“InstancePerDependency”或
  2. 使用单独的IoC容器进行后台作业。
  3. <强>更新

    Hangfire Autofac integration package引入了InstancePerBackgroundJob()扩展方法,并建议Autofac支持注册多个范围,如下所示:

    builder.RegisterType<Database>()
           .InstancePerBackgroundJob()
           .InstancePerHttpRequest();
    

    但是,它仅适用于Hangfire.Autofac的1.2.0-beta1版本,该版本需要使用Hangfire 1.5.0-beta1。