I've just installed Hangfire package in my MVC website. I've created a Startup class
我刚刚在我的MVC网站上安装了Hangfire包。我创建了一个Startup类
[assembly: OwinStartup(typeof(Website.Startup))]
namespace Website
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
Hangfire.ConfigureHangfire(app);
Hangfire.InitializeJobs();
}
}
}
and a Hangfire class
和一个Hangfire课程
public class Hangfire
{
public static void ConfigureHangfire(IAppBuilder app)
{
app.UseHangfire(config =>
{
config.UseSqlServerStorage("DefaultConnection");
config.UseServer();
config.UseAuthorizationFilters();
});
}
public static void InitializeJobs()
{
RecurringJob.AddOrUpdate<CurrencyRatesJob>(j => j.Execute(), "* * * * *");
}
}
Also, I've created a new job in a separate class library
另外,我在一个单独的类库中创建了一个新工作
public class CurrencyRatesJob
{
private readonly IBudgetsRepository budgetsRepository;
public CurrencyRatesJob(IBudgetsRepository budgetsRepository)
{
this.budgetsRepository = budgetsRepository;
}
public void Execute()
{
try
{
var budgets = new BudgetsDTO();
var user = new UserDTO();
budgets.Sum = 1;
budgets.Name = "Hangfire";
user.Email = "email@g.com";
budgetsRepository.InsertBudget(budgets, user);
}
catch (Exception ex)
{
var message = ex.ToString();
throw new NotImplementedException(message);
}
}
}
So when I run the application, in the Hangfire's dashboard I get the following error:
因此,当我运行应用程序时,在Hangfire的仪表板中,我收到以下错误:
Failed An exception occurred during job activation.
System.MissingMethodException
No parameterless constructor defined for this object.
System.MissingMethodException: No parameterless constructor defined for this object.
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type)
at Hangfire.JobActivator.ActivateJob(Type jobType)
at Hangfire.Common.Job.Activate(JobActivator activator)
So, I'm a little lost here. What am I missing?
所以,我在这里有点失落。我错过了什么?
3 个解决方案
#1
It appears you have not connected Hangfire to the IoC container you are using and therefore it uses its default strategy to create a requested type, which in your specific example means calling:
您似乎没有将Hangfire连接到您正在使用的IoC容器,因此它使用其默认策略来创建请求的类型,在您的特定示例中,这意味着调用:
System.Activator.CreateInstance(typeof(CurrencyRatesJob));
Because the CurrencyRatesJob
class does not have a default parameterless constructor, this fails with the error message you show in your question.
由于CurrencyRatesJob类没有默认的无参数构造函数,因此会失败并显示您在问题中显示的错误消息。
To connect Hangfire to your IoC infrastructure, you need to create your own JobActivator
class that overrides the ActivateJob
method and uses the configured IoC container to create instances of the requested job types.
要将Hangfire连接到IoC基础结构,您需要创建自己的JobActivator类来覆盖ActivateJob方法,并使用配置的IoC容器创建所请求作业类型的实例。
An example that uses Unity as the container (UnityJobActivator
) can be found here and an example for the Funq
container (FunqJobActivator
) can be found here.
可以在此处找到使用Unity作为容器(UnityJobActivator)的示例,可以在此处找到Funq容器(FunqJobActivator)的示例。
The process is described in the Hangfire documentation, and standard implementations for several container types are available from the Hangfire github repo
Hangfire文档中描述了该过程,Hangfire github repo提供了几种容器类型的标准实现
#2
You need to inject the dependencies to get this working. Install nuget unity package :
您需要注入依赖项才能使其正常工作。安装nuget unity包:
Install-Package Hangfire.Unity
And then register on Global.asax you will have BootStraper initialise method.Navigate to boot strapper class and in initialise have following code,
然后在Global.asax上注册你将拥有BootStraper初始化方法。导航到启动strapper类并在初始化中有以下代码,
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
Complete code will look something like following if you are using Unity.
如果您使用Unity,完整代码将类似于以下内容。
public static class Bootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
GlobalConfiguration.Configuration.UseUnityActivator(container);
RegisterTypes(container);
return container;
}
#3
I found a pretty straightforward discussion here: Hangfire Discussion
我在这里找到了一个非常简单的讨论:Hangfire Discussion
I will include my sample code:
我将包含我的示例代码:
public class Job : IJob
{
private readonly IService _service;
private readonly IDbContext _context;
public Job()
{
// this needs to be here, although this won't be used in the actual running
}
public Job(IService service, IDbContext context) : this()
{
_service = service;
_context = context;
}
public override void Run(SomeModel searchLocationModel)
{
}
}
My actual invoke of Hangfire is below:
我实际调用的Hangfire如下:
IJob job = NinjectWebCommon.Kernel.TryGet<Job>();
RecurringJob.AddOrUpdate(job.ToString(), () => job.Run(model), Cron.Weekly, TimeZoneInfo.Utc);
#1
It appears you have not connected Hangfire to the IoC container you are using and therefore it uses its default strategy to create a requested type, which in your specific example means calling:
您似乎没有将Hangfire连接到您正在使用的IoC容器,因此它使用其默认策略来创建请求的类型,在您的特定示例中,这意味着调用:
System.Activator.CreateInstance(typeof(CurrencyRatesJob));
Because the CurrencyRatesJob
class does not have a default parameterless constructor, this fails with the error message you show in your question.
由于CurrencyRatesJob类没有默认的无参数构造函数,因此会失败并显示您在问题中显示的错误消息。
To connect Hangfire to your IoC infrastructure, you need to create your own JobActivator
class that overrides the ActivateJob
method and uses the configured IoC container to create instances of the requested job types.
要将Hangfire连接到IoC基础结构,您需要创建自己的JobActivator类来覆盖ActivateJob方法,并使用配置的IoC容器创建所请求作业类型的实例。
An example that uses Unity as the container (UnityJobActivator
) can be found here and an example for the Funq
container (FunqJobActivator
) can be found here.
可以在此处找到使用Unity作为容器(UnityJobActivator)的示例,可以在此处找到Funq容器(FunqJobActivator)的示例。
The process is described in the Hangfire documentation, and standard implementations for several container types are available from the Hangfire github repo
Hangfire文档中描述了该过程,Hangfire github repo提供了几种容器类型的标准实现
#2
You need to inject the dependencies to get this working. Install nuget unity package :
您需要注入依赖项才能使其正常工作。安装nuget unity包:
Install-Package Hangfire.Unity
And then register on Global.asax you will have BootStraper initialise method.Navigate to boot strapper class and in initialise have following code,
然后在Global.asax上注册你将拥有BootStraper初始化方法。导航到启动strapper类并在初始化中有以下代码,
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
Complete code will look something like following if you are using Unity.
如果您使用Unity,完整代码将类似于以下内容。
public static class Bootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
GlobalConfiguration.Configuration.UseUnityActivator(container);
RegisterTypes(container);
return container;
}
#3
I found a pretty straightforward discussion here: Hangfire Discussion
我在这里找到了一个非常简单的讨论:Hangfire Discussion
I will include my sample code:
我将包含我的示例代码:
public class Job : IJob
{
private readonly IService _service;
private readonly IDbContext _context;
public Job()
{
// this needs to be here, although this won't be used in the actual running
}
public Job(IService service, IDbContext context) : this()
{
_service = service;
_context = context;
}
public override void Run(SomeModel searchLocationModel)
{
}
}
My actual invoke of Hangfire is below:
我实际调用的Hangfire如下:
IJob job = NinjectWebCommon.Kernel.TryGet<Job>();
RecurringJob.AddOrUpdate(job.ToString(), () => job.Run(model), Cron.Weekly, TimeZoneInfo.Utc);