表达式主体应为 'MethodCallExpression' 类型

Expression body should be of type 'MethodCallExpression'

我有一个函数-

public async Task DoWork(Frequency value) { // do work }

这里的想法是将此功能作为一个循环作业添加到 Hangfire。

明确添加作业有效,就像这样 -

RecurringJob.AddOrUpdate("triggerId", () => DoWork(frequency), Cron.Daily())

但是,如果我想创建一个函数来添加触发器

private void AddTrigger(string triggerId, Frequency frequency, Func<Frequency, Task> trigger)
{
    RecurringJob.AddOrUpdate(triggerId, () => trigger(frequency), Cron.Daily());
}

我得到一个错误 Expression body should be of type 'MethodCallExpression'

当我调试时,它们似乎是同一类型的对象。我在这里遗漏了什么导致了这个错误?

() => trigger(frequency)    {Method = {System.Threading.Tasks.Task <<>m0>b__0()}}   object {System.Func<System.Threading.Tasks.Task>}
() => DoWork(frequency)     {Method = {System.Threading.Tasks.Task <<>m0>b__0()}}   object {System.Func<System.Threading.Tasks.Task>}

您正在调用的 RecurringJob.AddOrUpdate 重载接受 Expression<Func<Task>>。这是一个 表达式树 表示 returns 任务的调用。

不幸的是,RecurringJob.AddOrUpdate 需要表达式树来表示方法调用 - 它调用 Job.FromExpression,最终在 this code 中结束。每个 Job 最终都是从 MethodInfo 构建的。您的 lambda 表达式是通过参数调用,因此它不起作用。

您可以将调用包装在方法调用中,如下所示 - 我不知道它是否真的有效……您可能会发现您最终得到了很多名为“Execute”的作业".

private void AddTrigger(string triggerId, Frequency frequency, 
                        Func<Frequency, Task> trigger)
{
    var wrapper = new TriggerWrapper(() => trigger(frequency));
    RecurringJob.AddOrUpdate(triggerId, () => wrapper.Execute(), Cron.Daily());
}

private class TriggerWrapper
{
    private Func<Task> func;

    internal TriggerWrapper(Func<Task> func) => this.func = func;

    public Task Execute() => func();
}