3

我们正在开发一个 Windows 应用程序,该应用程序必须定期启动可能需要一些时间的操作。我们已经进入了让这些操作在 BackgroundWorker 上运行的模式,并为每个操作编写一个快速 WinForm,在其中您将必要的参数传递给表单,表单连接 BackgroundWorker 并进行函数调用,并且表单显示输出(进度条移动,文本填充更新等)。

现在很明显,这种形式非常千篇一律。表单副本之间真正不同的唯一部分是在哪个对象上调用哪个方法。所以我们想做的是让它成为通用的,这样我们就可以采用形式,传入一个对象(或 null 用于静态调用?),一个函数名和一个参数数组,然后让它“运行”从那里。我们已经能够通过反射做到这一点。在这种情况下,我们不喜欢反射的地方是缺乏强类型;诸如拼写错误的方法调用之类的事情在运行时被捕获,而不是编译时。现在有什么可用的东西可以使它更加优雅和健壮吗?我听说有人在谈论诸如代表和表达式树之类的东西;但我不确定前者是否适用,但我对后者仍然有些不知所措。

4

3 回答 3

6

制作一个通用表单并将其传递给指向它应该在 BackgroundWorker 上运行的方法的委托,这将是一个明智的解决方案。

您可以让 Form 构造函数将通用委托(Action 可能是一个好主意)作为参数,并在构造函数中传递与 Action 的签名匹配的 lambda 表达式)。然后,对于每个动作,您只需要指定适当的 lambda 表达式。

请记住,lambda 表达式可以捕获局部变量,因此您将能够调用您之前执行的任何逻辑并传递相同的参数。

于 2009-04-06T17:55:36.410 回答
3

您可能还想查看 Lambda 函数。我在使用泛型时专门使用它们。否则,代表可能会正常工作。

于 2009-04-06T18:01:29.360 回答
2

您可以做的一件事是创建几种不同的方法(一种用于没有参数的方法,一种用于具有一个参数的方法等),如下所示:

public static void DisplayForm(Action action) {
    DisplayFormUsingInvoke(action);
}

public static void DisplayForm<T>(Action<T> action, T param) {
    DisplayFormUsingInvoke(action, param);
}

public static void DisplayForm<T,U>(Action<T,U> action, T param1, U param2) {
    DisplayFormUsingInvoke(action, param1, param2);
}

...

然后,您可以拥有一个实际完成工作的私有方法,类似于您当前的方法,但不暴露给客户端代码:

private static void DisplayFormUsingInvoke(Delegate d, params object[] parms) {
    // Edit this code to run it on the background thread, report progress, etc.
    d.DynamicInvoke(parms);
}

然后客户端代码将调用公共方法之一,该方法将强制要求提供正确数量和类型的参数。

于 2009-04-06T18:22:16.047 回答