我确信这主要是我对泛型和表达式缺乏了解,但我正在尝试创建一个Expression<Action<T>>
列表,以便在我处于提交状态后调用 BackgroundJob.Enqueue。
我有几个代码区域可能想要将作业排队,但他们不知道作业是否应该实际运行,直到代码的另一段发生,特别是保存到数据库。
我正在努力解决的是,当T明显不同时创建一个List<Expression<Action<T>>>
,并在准备就绪时将其传递给BackgroundJob.Enqueue。
public class HangfireQueue
{
private readonly IList<Expression<Action<object>>> _queuedItems;
public HangfireQueue()
{
_queuedItems = new List<Expression<Action<object>>>();
}
public virtual void EnqueueTask<T>( Expression<Action<T>> methodCall )
{
_queuedItems.Add( methodCall );
}
public void CommitUnitOfWork()
{
foreach ( var item in _queuedItems )
{
BackgroundJob.Enqueue( (Expression<Action>) item );
}
}
}
我已经尝试了许多不同的方法,这恰好是最新的尝试,有时我让它编译并且它在运行时不喜欢它,无法将Expression<Action<T>>
转换为Expression<Action>
这将是这里问题的一部分,更不用说 methodCall 不会被接受在列表中。
大概Enqueue
将Expression<Action>
作为参数 - 这是一个表达式,其计算结果为不带参数的void方法。
您正在尝试传递Expression<Action<T>>
- 评估为采用一个参数的 void 方法。编译器永远不会允许这样做。
请改用Expression<Action>
:
public class HangfireQueue
{
private readonly IList<Expression<Action>> _queuedItems;
public HangfireQueue()
{
_queuedItems = new List<Expression<Action>>();
}
public virtual void EnqueueTask(Expression<Action> methodCall)
{
_queuedItems.Add(methodCall);
}
public virtual void EnqueueTask<T>(Expression<Action<T>> methodCall, T p1)
{
_queuedItems.Add(() => methodCall.Compile()(p1));
}
public virtual void EnqueueTask<T1,T2>(Expression<Action<T1,T2>> methodCall, T1 p1, T2 p2)
{
_queuedItems.Add(() => methodCall.Compile()(p1, p2));
}
public void CommitUnitOfWork()
{
foreach (Expression<Action> item in _queuedItems)
{
BackgroundJob.Enqueue(item);
}
}
}
现在添加您的方法,使用 lambda 语法创建Expression<Action>
对象,这些对象将调用要排队的代码:
HangfireQueue q = new HangfireQueue();
q.EnqueueTask(AnyMethod, anyParameter);
q.EnqueueTask(() =>
{
AnyMethod(anyParameter);
OtherMethod("hello", "world");
});
q.CommitUnitOfWork();