Передача метода в другой метод для Hangfire Scheduler вместо использования жестко закодированного имени метода

Я использую Hangfire и пытаюсь просто запланировать простую работу. Это работает, если я жестко закодирую имя метода, который должен быть запущен в указанное время, но я хотел бы что-то более общее, то есть передать любой метод в этот код и позволить Hangfire выполнить его по расписанию.

Вот один из способов, которыми я пытался это сделать.

public static void ScheduleSingleRun(Activity parametersStorage, Action<Activity, int> scheduledFunction, int secondsDelay)
{
    TimeSpan offset = new TimeSpan(0, 0, secondsDelay);
    try
    {
        BackgroundJob.Schedule(() => 
            scheduledFunction(parametersStorage, secondsDelay), offset);
        return new HangfireSchedulerResponse("Scheduled successfully.", 0);          
        ... 

И вот как я называю эту функцию:

HangfireScheduler.ScheduleSingleRun(parameters, TestMethod, 15);

Где TestMethod - это имя метода в том же классе.

Этот код компилируется, но вызывает эту ошибку при запуске:

Expression body should be of type `MethodCallExpression`"

Я пробовал Action, Func<>, Delegate - ничего не получалось. Работает только указание явного имени метода:

BackgroundJob.Schedule(() => TestClass.TestMethod(parametersStorage, secondsDelay)

Что я делаю не так - есть ли способ просто передать имя метода / ссылку на Hangfire вместо жесткого его кодирования?

1 ответ

Решение

Смотрите пример ниже. В вашем случае я думаю, что вы должны передать выражение. В моем примере вы должны передать переменную "lambda" в свой метод BackgroundJob.Schedule.

class Program
{
    static void Main(string[] args)
    {
        int param1Value = 2;
        object param2Value = "hello";

        var param1 = Expression.Parameter(typeof(int));
        var param2 = Expression.Parameter(typeof(object));

        var testMethodInfo = typeof(MyClass).GetMethod("TestMethod", BindingFlags.Public | BindingFlags.Static);
        var exp = Expression.Call(testMethodInfo, param1, param2);

        var lambda = Expression.Lambda<Action<int, object>>(exp, param1, param2);

        lambda.Compile().Invoke(param1Value, param2Value);
    }
}

static class MyClass
{
    public static void TestMethod(int param1, object param2)
    {
        Console.WriteLine(param1);
        Console.WriteLine(param2?.ToString());
    }
}
Другие вопросы по тегам