Hangfire - для этого объекта не определен конструктор без параметров

Я использую Hangfire для выполнения некоторых повторяющихся заданий, но получаю следующее исключение:

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.JobActivator.SimpleJobActivatorScope.Resolve(Type type)
   at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_0.<PerformJobWithFilters>b__0()
   at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
   at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_1.<PerformJobWithFilters>b__2()
   at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
   at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

Я инициализировал свой Hangfire в моем AppBuilder:

Hangfire.GlobalConfiguration.Configuration.UseSqlServerStorage(ConfigurationManager.ConnectionStrings[ConfigurationKeys.DbDefaultConnectionName].ConnectionString);

        app.UseHangfireDashboard();
        app.UseHangfireServer();

В основном, в моем приложении вы можете создавать контракты. Каждый раз, когда создается контракт, я добавляю новое повторяющееся задание, используя следующую строку:

RecurringJob.AddOrUpdate(() => AutomaticMovementsCreation(contractToCreate.DebitValue, contractId, descriptionId.Result), Cron.Minutely);

Это создатель класса, в который добавляется RecurringJob:

public ContractServiceImpl(IAuthService authService, IContractStore contractStore)
{
    _contractStore = contractStore;
    _authService = authService;
}

_contractStore используется методом AutomaticMovementsCreation,

Я думаю, что это что-то из-за зависимой инъекции, но я действительно не знаю, что именно и как это решить. Кстати, я использую контейнер Unity для регистрации зависимостей моего приложения.

Весь запуск:

public void Configuration(IAppBuilder app)
{
    var httpConfiguration = new HttpConfiguration();

    ConfigureUnity(app, httpConfiguration);
    ConfigureWebApi(httpConfiguration);
    ConfigureAuth(app);

    //Set configuration into Owin
    app.UseWebApi(httpConfiguration);

    Hangfire.GlobalConfiguration.Configuration.UseSqlServerStorage(ConfigurationManager.ConnectionStrings[ConfigurationKeys.DbDefaultConnectionName].ConnectionString);

    app.UseHangfireDashboard();
    app.UseHangfireServer();

}

public void ConfigureUnity(IAppBuilder app, HttpConfiguration config) {
    UnityContainer container = UnityConfig.GetConfiguredContainer() as UnityContainer;

    if (app.GetDataProtectionProvider() == null) {
        app.UseAesDataProtectionProvider();
    }

    IDataProtectionProvider dataProtectionProvider = app.GetDataProtectionProvider();

    container.RegisterInstance(dataProtectionProvider);


    app.CreatePerOwinContext(() =>
        UnityConfig.GetConfiguredContainer().Resolve<ApplicationUserManager‌​>()
    );

    config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());

}

В этом методе GetConfiguredContainer где я регистрирую свои услуги и хранилища данных.

3 ответа

Решение

Решил это, используя следующий код:

    Hangfire.GlobalConfiguration.Configuration.UseActivator(new ContainerJobActivator(container));
    Hangfire.GlobalConfiguration.Configuration.UseSqlServerStorage(ConfigurationManager.ConnectionStrings[ConfigurationKeys.DbDefaultConnectionName].ConnectionString);
    app.UseHangfireDashboard();
    app.UseHangfireServer();




 public class ContainerJobActivator : JobActivator
    {
        private IUnityContainer _container;

        public ContainerJobActivator(UnityContainer container)
        {
            _container = container;
        }

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

Во-первых, вам нужно создать экземпляр UnityContainer (при запуске), загрузить конфигурацию из web.config и, наконец, связать контейнер с вашей HttpConfiguration.

Я не помню код точно, но это выглядит так:

var container = new UnityContainer(); 
container.LoadConfiguration(); 
config = new HttpConfiguration(); 
config.DependencyResolver = new UnityDependencyResolver(container);
app.UseWebApi(config);   // Something like that

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

Install-Package Hangfire.Unity

А затем зарегистрируйтесь на Global.asax, у вас будет метод инициализации BootStraper. Перейдите к загрузке класса strapper и при инициализации получите следующий код:

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;
 }
Другие вопросы по тегам