2015-05-04 2 views
5

Я только что установил пакет Hangfire на моем веб-сайте MVC. Я создал класс запускаНет конструктора без параметров для этого объекта - Планировщик Hangfire

[assembly: OwinStartup(typeof(Website.Startup))] 

namespace Website 
{ 
    public partial class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      Hangfire.ConfigureHangfire(app); 
      Hangfire.InitializeJobs(); 
     } 
    } 
} 

и класс замедленного воспламенения

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(), "* * * * *"); 
    } 
} 

Кроме того, я создал новую работу в отдельной библиотеке классов

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 protected]"; 

      budgetsRepository.InsertBudget(budgets, user); 
     } 
     catch (Exception ex) 
     { 
      var message = ex.ToString(); 
      throw new NotImplementedException(message); 
     } 
    } 
} 

Так что, когда я запустите приложение, на приборной панели 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) 

Итак, я немного здесь потерялся. Что мне не хватает?

+0

У вас есть код регистрации, где hangfire получает уведомление о том, какие классы он должен использовать? – dbarnes

+0

Я думаю, что у меня его нет. Я не помню, чтобы прочитать об этом. Можете ли вы рассказать мне больше? –

+0

Ну, я не эксперт по фейджу, но ясно, что он пытается разрешить «CurrencyRatesJob», но он не может, потому что он не знает, к чему должен быть разрешен «IBudgetsRepository». Вот почему вы получаете пустую ошибку конструктора. Возможно, этот пост может помочь http://stackoverflow.com/questions/26615794/hangfire-autofac-with-mvc-app-injection-fails. – dbarnes

ответ

5

Похоже, вы не подключили замедленное воспламенение к контейнеру IoC вы используете, и поэтому он использует свою стратегию по умолчанию, чтобы создать требуемый тип, который в вашем конкретном примере означает вызов:

System.Activator.CreateInstance(typeof(CurrencyRatesJob)); 

Поскольку CurrencyRatesJob класса не имеет конструктора без параметров по умолчанию, это не удается с сообщением об ошибке, которое вы укажете в своем вопросе.

Чтобы подключить Hangfire к вашей инфраструктуре IoC, вам необходимо создать свой собственный класс JobActivator, который переопределяет метод ActivateJob и использует сконфигурированный контейнер IoC для создания экземпляров заданных типов заданий.

В качестве примера, который использует Unity в качестве контейнера (UnityJobActivator) можно найти here и пример для Funq контейнера (FunqJobActivator) можно найти here.

Процесс описан в Hangfire documentation и стандартные реализации для нескольких типов контейнеров доступны из Hangfire github repo

+0

Ну, я использую Ninject, и я видел, что есть пакет Nuget (Hangfire.Ninject), но я не уверен, как с ним работать. Я попытался создать конструктор без параметров в задании, и он был выполнен, но у меня не было объекта IBudgetsRepository. –

+0

@MarianEne, правильно, потому что для этого вам нужен IoC, чтобы разрешить зависимость IBubgetsRepository в качестве экземпляра, введенного в ваш 'CurrencyRatesJob'. Используя этот пакет Nuget, вы должны использовать метод расширения 'UseNinjectActivator' при запуске:' GlobalConfiguration.Configuration.UseNinjectActivator (ядро); 'с' kernel' является экземпляром вашего ядра Ninject. – Alex

+0

, поэтому я немного смущен, где я должен добавить это: 'var kernel = new StandardKernel(); GlobalConfiguration.Configuration.UseNinjectActivator (ядро); '. Если я добавлю его в Global.asax, я получу 'Ninject.ActivationException'; если я добавлю его в задание, сразу после «try» я получаю такое же исключение без паратетера. –

0

Я нашел довольно простое обсуждение здесь: Hangfire Discussion

Я включать мой пример код:

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) 
    { 
    } 
} 

Моя фактическая Invoke из замедленного воспламенения ниже:

IJob job = NinjectWebCommon.Kernel.TryGet<Job>(); 

RecurringJob.AddOrUpdate(job.ToString(),() => job.Run(model), Cron.Weekly, TimeZoneInfo.Utc); 
1

Вам нужно ввести зависимости, чтобы заставить это работать. Установить NuGet пакет единства:

Install-Package Hangfire.Unity 

А потом зарегистрироваться на Global.asax вы будете иметь BootStraper инициализирует method.Navigate для загрузки класса обвязывающего и Initialise имеете следующий код,

DependencyResolver.SetResolver(new UnityDependencyResolver(container)); 

Полный код будет выглядеть что-то вроде следующего, если вы используете 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; 
} 
Смежные вопросы