表达式主体应为“MethodCallExpression”类型

Adj*_*jit 1 c# delegates hangfire

我有一个功能 -

public async Task DoWork(Frequency value) { // do work }
Run Code Online (Sandbox Code Playgroud)

这里的想法是将此功能作为重复作业添加到 Hangfire 中。

显式添加作业是有效的,如下所示 -

RecurringJob.AddOrUpdate("triggerId", () => DoWork(frequency), Cron.Daily())
Run Code Online (Sandbox Code Playgroud)

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

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

我收到一个错误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>}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

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

不幸的是,RecurringJob.AddOrUpdate需要表达式树来表示方法调用——它调用Job.FromExpression,最终出现在这段代码中。每个Job最终都是从MethodInfo. 您的 lambda 表达式是通过参数进行的调用,因此它不起作用。

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

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();
}
Run Code Online (Sandbox Code Playgroud)