繁体   English   中英

有没有更好的方法在ASP.net核心上使用hangfire和structuremap?

[英]Is there any better way using hangfire with structuremap on ASP.net core?

我在asp.net核心上使用了与hangfire的结构图,在应用程序上没有错误,但是即使数据已经在数据库上,也没有处理队列/调度任务。 这是我的代码段配置

public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // setup automapper
        var config = new AutoMapper.MapperConfiguration(cfg =>
        {
            cfg.AddProfile(new AutoMapperProfileConfiguration());
        });

        var mapper = config.CreateMapper();
        services.AddSingleton(mapper);


        // Bind settings parameter
        services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);
        services.Configure<RouteOptions>(options => options.LowercaseUrls = true);
        services.AddDbContext<DefaultContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddHangfire(options => 
            options.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));

        services.AddMvc();
        // ASP.NET use the StructureMap container to resolve its services.
        return ConfigureIoC(services);
    }

    public IServiceProvider ConfigureIoC(IServiceCollection services)
    {
        var container = new Container();

        GlobalConfiguration.Configuration.UseStructureMapActivator(container);

        container.Configure(config =>
        {
            // Register stuff in container, using the StructureMap APIs...
            config.Scan(_ =>
            {
                _.AssemblyContainingType(typeof(Startup));
                _.WithDefaultConventions();
                _.AddAllTypesOf<IApplicationService>();
                _.ConnectImplementationsToTypesClosing(typeof(IOptions<>));
            });
            config.For<JobStorage>().Use(new SqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
            config.For<IJobFilterProvider>().Use(JobFilterProviders.Providers);

            config.For<ILog>().Use(c => LoggerFactory.LoggerFor(c.ParentType)).AlwaysUnique();
            XmlDocument log4netConfig = new XmlDocument();
            log4netConfig.Load(File.OpenRead("log4net.config"));

            var repo = LogManager.CreateRepository(
                Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy));

            XmlConfigurator.Configure(repo, log4netConfig["log4net"]);
            //Populate the container using the service collection
            config.Populate(services);
        });

        return container.GetInstance<IServiceProvider>();
    }

有没有更好的方法在asp.net核心上使用hangfire和structuremap? 我错过了什么,所以hangfire不能正常工作?

我的Hangfire结构图实现

using Hangfire;
using StructureMap;

namespace Lumochift.Helpers
{
    /// <summary>
    /// Bootstrapper Configuration Extensions for StructureMap.
    /// </summary>
    public static class StructureMapBootstrapperConfigurationExtensions
    {
        /// <summary>
        /// Tells bootstrapper to use the specified StructureMap container as a global job activator.
        /// </summary>
        /// <param name="configuration">Bootstrapper Configuration</param>
        /// <param name="container">StructureMap container that will be used to activate jobs</param>
        public static void UseStructureMapActivator(this GlobalConfiguration configuration, IContainer container)
        {
            configuration.UseActivator(new StructureMapJobActivator(container));
        }
    }
}


using Hangfire;
using StructureMap;
using System;

namespace Lumochift.Helpers
{
    public class StructureMapJobActivator : JobActivator
    {
        private readonly IContainer _container;

        /// <summary>
        /// Initializes a new instance of the <see cref="StructureMapJobActivator"/>
        /// class with a given StructureMap container
        /// </summary>
        /// <param name="container">Container that will be used to create instances of classes during
        /// the job activation process</param>
        public StructureMapJobActivator(IContainer container)
        {
            if (container == null) throw new ArgumentNullException(nameof(container));

            _container = container;
        }

        /// <inheritdoc />
        public override object ActivateJob(Type jobType)
        {
            return _container.GetInstance(jobType)
        }

        /// <inheritdoc />
        public override JobActivatorScope BeginScope(JobActivatorContext context)
        {
            return new StructureMapDependencyScope(_container.GetNestedContainer());
        }


        private class StructureMapDependencyScope : JobActivatorScope
        {
            private readonly IContainer _container;

            public StructureMapDependencyScope(IContainer container)
            {
                _container = container;
            }

            public override object Resolve(Type type)
            {
                return _container.GetInstance(type);
            }

            public override void DisposeScope()
            {
                _container.Dispose();
            }
        }
    }
}

控制器上的示例hangfire调用

    BackgroundJob.Enqueue<CobaService>((cb) => cb.GetCoba());
    BackgroundJob.Schedule<CobaService>((cb) => cb.GetCoba(), TimeSpan.FromSeconds(5) );

截图: Hangfire队列 预定的工作

您应该使用Hangfire.AspNetCore nuget包。

它使用AspNetCoreJobActivator作为默认作业激活器,因此您不必创建自己的作业激活器。

AspNetCoreJobActivator使用IServiceScope.ServiceProvider.GetRequiredService(type)方法来解析依赖关系。 您从ConfigureServices返回的相同ServiceProvider,其中包含由structuremap配置的所有服务。

AddHangfire方法的实现

您应该返回StructureMapDependencyScope与嵌套容器BeginScope

public override JobActivatorScope BeginScope(JobActivatorContext context)
{
    return new StructureMapDependencyScope(_container.GetNestedContainer());
}

另外,我不会将容器与Activator.CreateInstance混合使用,只需在ActivateJob使用_container.GetInstance(jobType)

主要问题不在于使用hangfire的实现结构图。 起初虽然我认为这是因为SQL服务器版本但降级后降级问题仍然相同。 只有队列但没有激活任务。 更改配置设置后,我发现了问题。

"DefaultConnection": "Server=127.0.0.1,1434;Database=db;User Id=sa;Password=pass;MultipleActiveResultSets=true"

这是问题,我在使用没有指定端口或使用端口1433正常运行的所有内容后使用端口1434 再也没有工作卡在队列上了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM