c# - 在 WebApi 中使用 Autofac 进行 Hangfire

标签 c# asp.net-web-api autofac hangfire hangfire-autofac

我在 startup.cs 中有以下配置,但我收到错误,尽管我已经安装了 Hangifre.Autofac nuget 包并进行了配置。

No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.

Startup.cs

 public void Configuration(IAppBuilder app)
        {

            var builder = new ContainerBuilder();


            //if (AppConfigHelper.PlatformEnvironment == PlatformEnvironment.LocalHost)
            builder.RegisterType<NLogLogger>().As<ILogger>().InstancePerLifetimeScope();
            //else
            //builder.RegisterType<SentryLogger>().As<ILogger>().InstancePerLifetimeScope();

            //builder.RegisterWebApiFilterProvider(configuration);

            // REGISTER CONTROLLERS SO DEPENDENCIES ARE CONSTRUCTOR INJECTED
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

            //These lines warm up dlls and load into memory for automatic regisration
            var r = new ReplyRepository(null);
            var s = new BankService();

            builder.RegisterModule(new SelfRegisterModule());
            builder.RegisterModule(new RepositoryModule());
            builder.RegisterModule(new ServiceModule());
            builder.RegisterModule(new EFModule());


            builder
                   .RegisterType<ApplicationOAuthProvider>()
                   .As<IOAuthAuthorizationServerProvider>()
                   .PropertiesAutowired() // to automatically resolve IUserService
                   .SingleInstance(); // you only need one instance of this provider

            builder.RegisterType<SellutionUserStore>().As<IUserStore<ApplicationUser, int>>().InstancePerBackgroundJob().InstancePerRequest();
            builder.RegisterType<SellutionUserManager>().AsSelf().InstancePerBackgroundJob().InstancePerRequest();
            builder.RegisterType<SellutionRoleManager>().AsSelf().InstancePerBackgroundJob().InstancePerRequest();
            builder.RegisterType<SellutionSignInManager>().AsSelf().InstancePerBackgroundJob().InstancePerRequest();
            builder.Register<IAuthenticationManager>(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerBackgroundJob().InstancePerRequest();
            builder.Register<IDataProtectionProvider>(c => app.GetDataProtectionProvider()).InstancePerBackgroundJob().InstancePerRequest();

            builder.RegisterType<TicketDataFormat>().As<ISecureDataFormat<AuthenticationTicket>>();

            builder.RegisterType<TicketSerializer>().As<IDataSerializer<AuthenticationTicket>>();
            builder.Register(c => new DpapiDataProtectionProvider("Sellution360").Create("ASP.NET Identity")).As<IDataProtector>();

            builder.RegisterType<CurrencyRatesJob>().AsSelf().InstancePerBackgroundJob();

            // BUILD THE CONTAINER
            var container = builder.Build();

            Hangfire.GlobalConfiguration.Configuration.UseAutofacActivator(container);
            JobActivator.Current = new AutofacJobActivator(container);


            // REPLACE THE MVC DEPENDENCY RESOLVER WITH AUTOFAC
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            // Set the dependency resolver for Web API.
            var webApiResolver = new AutofacWebApiDependencyResolver(container);
            GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;

            // Set the dependency resolver for MVC.
            var mvcResolver = new AutofacDependencyResolver(container);
            DependencyResolver.SetResolver(mvcResolver);


            // Register the Autofac middleware FIRST, then the Autofac MVC middleware.
            app.UseAutofacMiddleware(container);
            app.UseAutofacMvc().UseCors(CorsOptions.AllowAll);
            app.UseAutofacWebApi(GlobalConfiguration.Configuration).UseCors(CorsOptions.AllowAll); ;

            IocManager.Instance.IocContainer = container;

            ConfigureAuth(app);
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();

            Hangfire.GlobalConfiguration.Configuration.UseSqlServerStorage("DefaultConnection");
            app.UseHangfireDashboard();
            app.UseHangfireServer();

            RecurringJob.AddOrUpdate<CurrencyRatesJob>(j => j.Execute(), Cron.Minutely);
        }

CurrencyRatesJob.cs

 public class CurrencyRatesJob
    {
        private readonly ILogger _logger;
        private readonly IBusinessTypeService _businessTypeService;

        public CurrencyRatesJob(ILogger logger, IBusinessTypeService businessTypeService)
        {
            _logger = logger;
            _businessTypeService = businessTypeService;
        }

        public void Execute()
        {
            var types = _businessTypeService.GetBusinessTypes();
            _logger.Log("waqar");

        }
    }

最佳答案

InstancePerBackgroundJob 使用 BackgroundJobScope 标签创建 Per Macthing Life Time 作用域。但是 Per Request 实例在另一个带有 Request 标签的生命周期范围内被解析。因此,当您尝试在 BackgroundJobScope 生命周期中解析 Per Request 对象时,它会出错。它说,你只能在 Request 生命周期内解决我,而不是在 root 或其他。因此,您应该使用 Per Life Time Scope 而不是 Per Request

所以这些 Per Life Time Scope 注册的对象将获得 parent 的生命周期。如果它是单例,他们将成为根。如果他们的父生命周期是请求的,他们将生活在这个请求范围内。 InstancePerBackgroundJob 也是一样,它们将存在于 BackgroundJobScope 生命周期范围内。

如果背景对象使用请求生命周期范围,那么背景对象有另一个生命周期范围是有好处的,您的对象可以在请求完成时被释放。此外,如果它们在根范围内,它们将永远不会被释放。

关于c# - 在 WebApi 中使用 Autofac 进行 Hangfire,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35534860/

相关文章:

c# - 如何使用 C# 绘制 3D 管的下半部分

autofac - 如何将受控生命周期关系类型(即 Owned<T>)与委托(delegate)工厂相结合?

c# - user.config 未在本地应用程序数据中生成

c# - 检查 Page.RouteData.Values 是否有值

c# - 应用程序域的用途是什么?

c# - 向breececontroller发送大的json数据失败

c# - 将字符串作为包含斜线或为空的 uri 参数传递

c# - ASP.Net Web 应用程序连接到主机 SQL 数据库

c# - 在 Autofac 中注册时如何避免使用 new 两次

dependency-injection - Autofac 未解决模型绑定(bind)器依赖项