Hangfire
Hangfire copied to clipboard
Make `JobActivatorScope` instance available in the `PerformContext`
Please release the latest Hangfire.Autofac.
Need the configure action callback API that was recently added.
Thanks.
Also, please change the AutofacScope::Resolve implementation to
public override object Resolve(Type type) {
return ActivatorUtilities.GetServiceOrCreateInstance( _lifetimeScope.Resolve<IServiceProvider>(), type);
}
Could you share more details regarding the new callback API that's missing? E.g. what's the current behavior, what's expected behavior, what compiler error or exception you see with the current implementation?
The new API was added after the latest release.
May I ask you to be more specific regarding the new API, e.g. which type, method and parameters are required in your case? Otherwise it's not possible to even test the resulting changes.
Sorry for confusion, what I'm asking is just to release the latest version of Hangfire.Autofac with this commit that is not included in 2.6.0
Also, please change the AutofacScope::Resolve implementation to
public override object Resolve(Type type) {
return ActivatorUtilities.GetServiceOrCreateInstance( _lifetimeScope.Resolve<IServiceProvider>(), type);
}
Another feature request, would you please add IServiceProvider optional getter to PerformContext to allow HF filters to resolve dependencies from current DI scope.
Hello, I have released Hangfire.Autofac 2.7.0 yesterday with the new scope configuration action feature. However, we can't add ActivatorUtilities usage currently, because should reconsider dependencies first (as it requires Microsoft.Extensions.DependencyInjection one). As I understand, this is to support activating non-registered services, right?
I will also think about PerformContext-related change as this feature will make it simpler to use dependency injection in filters.
Thanks
I think you can add Microsoft.Extensions.DependencyInjection because currently, Hangfire.Autofac can't be used without AspCore's JobActivator, which already has it as dependency.
Not quite, Hangfire.Autofac doesn't depend on ASP.NET Core at all, that JobActivator class is Hangfire.Core's abstraction that doesn't have any references to ASP.NET Core. I think that some other kind of abstraction is required here.
Hm, just realized that JobActivator class is simply not available in the Worker class, where a PerformContext class is created, and it's treated as an implementation detail of the CoreBackgroundJobPerformer class. Actually, it's possible to pass the IServiceProvider instance in the following way:
public sealed class DependencyInjectionExample : IServerFilter
{
private readonly IServiceProvider _serviceProvider;
public DependencyInjectionExample(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void OnPerforming(PerformingContext context)
{
var service = _serviceProvider.GetRequiredService<IMyService>();
}
public void OnPerformed(PerformedContext context)
{
}
}
services.AddHangfire((provider, configuration) => configuration
.UseFilter(new DependencyInjectionExample(provider))
Not quite, Hangfire.Autofac doesn't depend on ASP.NET Core at all, that
JobActivatorclass is Hangfire.Core's abstraction that doesn't have any references to ASP.NET Core. I think that some other kind of abstraction is required here.
You are right, it doesn't depend (in .csproj), but you haven't provided Autofac Module to register Hangfire, only via IServiceCollection extension. And it already has the reference to ActivatorUtilities.
Hm, just realized that
JobActivatorclass is simply not available in theWorkerclass, where aPerformContextclass is created, and it's treated as an implementation detail of theCoreBackgroundJobPerformerclass. Actually, it's possible to pass theIServiceProviderinstance in the following way:public sealed class DependencyInjectionExample : IServerFilter { private readonly IServiceProvider _serviceProvider; public DependencyInjectionExample(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public void OnPerforming(PerformingContext context) { var service = _serviceProvider.GetRequiredService<IMyService>(); } public void OnPerformed(PerformedContext context) { } }services.AddHangfire((provider, configuration) => configuration .UseFilter(new DependencyInjectionExample(provider))
The filter here uses new DependencyInjectionExample(provider), where provider is a root scope, but with Hangfire.Autofac you can register services with newly created scope. They won't be resolvable from the provider. (link to Action ), I'm registering services with ContainerBuilder based on JobActivatorContext
Good point, @jvmlet! Unfortunately, the activator scope is created after IServerFilter.OnPerforming method is already finished and has a very narrow scope, so we can't implement this in the current version.
The goal here is to make it accessible also in IServerFilter implementations, as a property in the PerformContext class to allow them resolving the same services as the background job itself. While it doesn’t make much sense with regular IoC containers, some advanced ones, like Autofac that allows registering custom services for created scopes, can receive big improvements. Also, ASP.NET Core’s IoC container implementation should also reach this point sooner or later, given the importance of this feature.
OK, so if scope will be created before executing IServerFilter, resolution of services from PerformingContext registered as scoped will be working as expected , right (and not from root scope)? This should work even with simple DI implementations as MS's one.