2015-05-04 24 views
5

Ho appena installato il pacchetto Hangfire nel mio sito Web MVC. Ho creato una classe di avvioNessun costruttore parametrico definito per questo oggetto - Utilità di pianificazione Hangfire

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

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

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

Inoltre, ho creato un nuovo lavoro in una libreria di classe separata

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

Così, quando ho eseguire l'applicazione, nel cruscotto Hangfire ho il seguente errore:

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) 

Quindi, sono un po 'perso qui. Cosa mi manca?

+0

Avete il codice di registro in cui il segnale di blocco viene avvisato di quali classi deve essere utilizzato? – dbarnes

+0

Penso di non averlo. Non ricordo di aver letto su questo. Mi puoi dire di più? –

+0

Beh, non sono un esperto di fuochi d'artificio, ma è chiaro che sta cercando di risolvere il 'CurrencyRatesJob', ma non può perché non sa a cosa deve essere risolto il'IBudgetsRepository'. Questo è il motivo per cui ottieni l'errore del costruttore vuoto. Forse questo post può aiutare http://stackoverflow.com/questions/26615794/hangfire-autofac-with-mvc-app-injection-fails. – dbarnes

risposta

5

Sembra che tu non hai collegato Hangfire al contenitore IoC che si sta utilizzando e quindi utilizza la propria strategia di default per creare un tipo di richiesta, che nel tuo esempio specifico significa chiamare:

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

Poiché la classe CurrencyRatesJob non ha un costruttore parametrico predefinito, questo fallisce con il messaggio di errore che mostri nella tua domanda.

Per collegare Hangfire all'infrastruttura IoC, è necessario creare la propria classe JobActivator che sostituisce il metodo ActivateJob e utilizza il contenitore IoC configurato per creare istanze dei tipi di lavoro richiesti.

Un esempio che utilizza l'unità del contenitore (UnityJobActivator) sono riportate here e un esempio per la Funq contenitore (FunqJobActivator) sono riportate here.

Il processo è descritto nel Hangfire documentation, e le implementazioni standard per diversi tipi di contenitori sono disponibili presso il Hangfire github repo

+0

Bene, sto usando Ninject e ho visto che esiste un pacchetto Nuget (Hangfire.Ninject), ma non sono sicuro di come lavorarci. Ho provato a creare un costruttore senza parametri nel lavoro ed è stato eseguito, ma non avevo l'oggetto IBudgetsRepository. –

+0

@MarianEne, giusto, perché è quello che ti serve per IoC, per risolvere la dipendenza 'IBudgetsRepository' come istanza iniettata nel tuo' CurrencyRatesJob'. Usando il pacchetto Nuget, all'avvio avresti usato il metodo di estensione 'UseNinjectActivator':' GlobalConfiguration.Configuration.UseNinjectActivator (kernel); 'con' kernel' come istanza del tuo kernel Ninject. – Alex

+0

quindi sono un po 'confuso su dove dovrei aggiungere questo: 'var kernel = new StandardKernel(); GlobalConfiguration.Configuration.UseNinjectActivator (kernel); '. Se lo aggiungo a Global.asax ottengo un 'Ninject.ActivationException'; se lo aggiungo al lavoro, subito dopo il 'try' ottengo la stessa eccezione parateterless. –

0

ho trovato una discussione piuttosto semplice qui: Hangfire Discussion

I comprenderà il mio codice di esempio:

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

mio attuale invoke di Hangfire è qui sotto:

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

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

È necessario iniettare le dipendenze per ottenere questo funzionamento. Installare NuGet pacchetto di unità:

Install-Package Hangfire.Unity 

E poi registrarsi sul Global.asax si avrà BootStraper inizializzare method.Navigate per l'avvio di classe strapper e inizializzazione hanno codice seguente,

DependencyResolver.SetResolver(new UnityDependencyResolver(container)); 

completo del codice sarà qualcosa come seguire se stai usando 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; 
}