Urdar
Urdar

Reputation: 67

Hangfire jobs utilising Autofac IoC singletons sharing a interface

I cant seem to find any information about this and hope someone can help.

With a class "TestClass" inheriting ITestClass I can register an Autofac singleton with the following code:

builder.RegisterType<TestClass>().As<ITestClass>().SingleInstance();

Adding a job to Hangfire is just as easy:

RecurringJob.AddOrUpdate<ITestClass>(x => x.MethodInITestClass, Cron.MinuteInterval(1));

What I cant seem to figure out is how to register multiple classes as Autofac singletons all having the same interface and being able to create a Hangfire job for a specific singleton.

For instance, having an interface named ITest and classes TestClass1, TestClass2 and TestClass3 utilising this interface I would like to add a Hangfire job for TestClass2.

I thought maybe named singletons would be a solution which can be created easily:

builder.RegisterType<TestClass1>().Named<ITest>("TestClass1").SingleInstance();
builder.RegisterType<TestClass2>().Named<ITest>("TestClass2").SingleInstance();
builder.RegisterType<TestClass3>().Named<ITest>("TestClass3").SingleInstance();

However, adding a Hangfire job for TestClass2 seems impossible as Hangfire only takes a interface as an argument and the interface now has 3 related singletons.

I would also like to be able to resolve all singletons implementing this interface into a IEnumerable which also seems impossible with named singletons.

Any advice on this? I guess named singletons may be a dead end?

Upvotes: 1

Views: 811

Answers (2)

Urdar
Urdar

Reputation: 67

Thank you for your answer fknx! :)

I see that by registering like this:

builder.RegisterType<TestClass1>().AsSelf().As<ITestClass>().SingleInstance();

builder.RegisterType<TestClass2>().AsSelf().As<ITestClass>().SingleInstance();

builder.RegisterType<TestClass3>().AsSelf().As<ITestClass>().SingleInstance();

.. would enable me to resolve them all using the ITestClass. What I don't see is how I would be able to register a Hangfirejob for i.e. TestClass2?

Your proposal for solution if I don't have access to singleton types is working great!

Registering:

builder.RegisterType<TestClass1>().As<ITestClass1>().As<ITestClass>().SingleInstance();

builder.RegisterType<TestClass2>().As<ITestClass2>().As<ITestClass>().SingleInstance();

builder.RegisterType<TestClass3>().As<ITestClass3>().As<ITestClass>().SingleInstance();

Also, I have ITestClassX inheriting ITestClass so that if I resolve by ITestClassX or ITestClass I still have access to the same methods.

Adding a Hangfire job:

RecurringJob.AddOrUpdate<ITestClass2>("JobTitle", x => x.DoAJob(), Cron.MinuteInterval(5));

Upvotes: 0

fknx
fknx

Reputation: 1785

I don't think named or keyed services will help you here. I took a look at the JobActivator implementation and there does not seem to be a way to have the name or key available in the ActivateJob(Type jobType) method where the service is resolved.

However, adding a Hangfire job for TestClass2 seems impossible as Hangfire only takes a interface as an argument and the interface now has 3 related singletons.

I don't think this is correct, so you could use your singleton types (TestClass1, TestClass2, ...) directly when adding a job. To do so you would have to register your singletons AsSelf() as well:

builder.RegisterType<TestClass>().AsSelf().As<ITestClass>().SingleInstance();

You'll still be able to resolve all your singletons using the ITestClass interface. If you don't have access to your singleton types in the code where you are adding the job you'll have to add an interface for each singleton (ITestClass1, ITestClass2, ...) and then use these interfaces for creating the jobs.

Upvotes: 1

Related Questions