Plugin system gives "Cannot create an instance of an interface" error

Hi,

I’m trying to implement a plugin system of background tasks in an MVC application. The plugins implement an interface, and are not referenced in the MVC app. My goal is to have a dynamic plugin system where I can drop new plugins in the bin folder, and configure recurring jobs from these plugins via the MVC app.

The problem I have is that the Job is serialized as the interface, not as the actual class. Some code to add clarity:

public void AddOrUpdatePlugin(EnginePluginHangfireDto enginePluginHangfireDto)
{
     var instance = ObjectFactory.GetInstance(enginePluginHangfireDto.Type);
       
     RecurringJob.AddOrUpdate(
           enginePluginHangfireDto.Code, 
           () => (instance as IEnginePlugin).ExecutePlugin(), 
           enginePluginHangfireDto.Cron);
}

This job gets serialized as

{"Type":"MyNamespace.IEnginePlugin, MyNamespace.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", ...

So when the job gets executed, there is an error: "cannot create an instance of an interface"

I tried to add the recurring job through reflection, but this serialized to the type MethodBase.

Is it possible to extend the RecurringJob class so it can get an extra method like this:

public static void AddOrUpdate(RuntimeMethodInfo methodInfo, string cronExpression)
{
    var job = Job.FromRuntimeMethodInfo(methodInfo);
    ...
}

Or do you see another option without having to reference the plugin dll’s to the project?

Thanks,

Bart

1 Like

Hi,

I’m having the same problem :frowning:
Can I vote for this feature-request somehow?
Because this is the only thing holding me back from using Hangfire in my project.

Cheers,

Mitchell

You’ll be able to achieve this when the following issue will be implemented:

After this change, you’ll be able to use the following code:

var pluginType = instance.GetType();
var pluginMethod = instance.GetMethod("ExecutePlugin");
var job = new Job(pluginType, pluginMethod);

var manager = new RecurringJobManager();
manager.AddOrUpdate(id, job, cron);
2 Likes

Excellent, im also waiting for this functionality. Any idea when it will be released?

Thanks

I ran into the same issue of needing to create a Hangfire job from a list of interfaces and needing to enqueue it into a regular background job. Below is the solution that work for me in this scenario.

        var connector = new Connector();
        var client = new BackgroundJobClient(JobStorage.Current);
        /* Create initialization tasks */
        foreach (var task in connector.GetTasks()
                .Where(task =>task.Type == TaskType.Initialization).ToList())
        {
            var job = new Job(task.GetType(), 
                             task.GetType().GetMethod("Process"));
            client.Create(job, new EnqueuedState());
        }

The example above works great for reoccuring jobs, but I was needing a solution for jobs that I only need to run once on startup.