简体   繁体   English

避免为不同类中使用的类似背景工作人员重复代码

[英]Avoiding code duplication for similar backgroundworkers used in dissimilar classes

I have several classes that are all using backgroundWorker threads to run logic while updating a status bar on my main form. 我有几个类都在更新主窗体上的状态栏时都使用backgroundWorker线程来运行逻辑。

I'm finding that a lot of the set up and reporting code for the backgroundWorkers is the same in multiple classes, eg: 我发现, backgroundWorkers的许多设置和报告代码在多个类中是相同的,例如:

BackgroundWorker wkrBackground = new BackgroundWorker();
wkrBackground.WorkerReportsProgress = true;
wkrBackground.WorkerSupportsCancellation = true;
wkrBackground.RunWorkerCompleted += new RunWorkerCompletedEventHandler(wkrBackground_RunWorkerCompleted);
wkrBackground.ProgressChanged += new ProgressChangedEventHandler(wkrBackground_ProgressChanged);

I'm sure that I will not need to use backgroundWorkers in any other ways than this, so would like to avoid the duplication. 我敢肯定,除此以外,我将不需要使用任何其他方式使用backgroundWorkers ,因此希望避免重复。

I have considered the following options: 我考虑了以下选项:

  • Making all the classes that use the background worker inherit from the same abstract class so that I can put the worker creation method in that, as well as the wkrBackground_RunWorkerCompleted and wkrBackground_ProgressChanged 使所有使用后台工作程序的类都继承自同一抽象类,以便我可以在其中添加工作程序创建方法以及wkrBackground_RunWorkerCompletedwkrBackground_ProgressChanged
  • Extending backgroundWorker to give it a new constructor that sets WorkerReportsProgress and WorkerSupportsCancellation and using that class instead 扩展backgroundWorker以为其提供一个新的构造函数,该构造函数设置WorkerReportsProgressWorkerSupportsCancellation并改用该类
  • Creating a worker utility class with a createBackgroundWorker method (though these last two options would not avoid the duplication of the final two lines as the specifics of those methods would still be included in the original classes). 使用createBackgroundWorker方法创建工作程序实用程序类(尽管后两个选项不能避免最后两行的重复,因为这些方法的细节仍将包含在原始类中)。

I'm wondering if there is a standard way to deal with this kind of duplication? 我想知道是否存在处理这种重复的标准方法?

The final option seems reasonable to me - and you can avoid the duplication of the final two lines, and even the one that you missed (the DoWork event): 最后的选择似乎是合理的,我-你可以避开最后两行的重复,甚至说你错过了(在一个DoWork事件):

public static BackgroundWorker CreateBackgroundWorker
    (DoWorkEventHandler workHandler,
     ProgressChangedEventHandler progressHandler,
     RunWorkerCompletedEventHandler completedHandler)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.WorkerReportsProgress = true;
    worker.WorkerSupportsCancellation = true;
    worker.DoWork += workHandler;
    worker.ProgressChanged += progressHandler;
    worker.RunWorkerCompleted += completedHandler;
}

Then call that with (say): 然后用(say)调用它:

BackgroundWorker = BackgroundWorkerHelper.CreateBackgroundWorker(
    wkrBackground_DoWork, wkrBackground_ProgressChanged,
    wkrBackground_RunWorkerCompleted);

Alternatively, having an interface with a method for each of the DoWork , ProgressChanged and RunWorkerCompleted events would be pretty sweet too, as per Matthew's suggestion... although it makes those three methods effectively public when they can otherwise be private. 或者,按照Matthew的建议,为每个DoWorkProgressChangedRunWorkerCompleted事件的方法提供接口也很不错……尽管这使这三种方法可以在不公开的情况下有效地公开。 It might help with testing, mind you... 请注意,这可能有助于测试。

I'd create a Controller class to hold the logic. 我将创建一个Controller类来保存逻辑。

Firstly, you would have to identify the common logic between between the display classes and encapsulate it as a set of methods specified in an interface. 首先,您必须确定显示类之间的通用逻辑,并将其封装为接口中指定的一组方法。 For the sake of argument, let's call that interface ICommonUiMethods . 为了便于讨论,我们将该接口ICommonUiMethods

Then, you would write a controller class which had a constructor to which you passed a BackgroundWorker and an ICommonUiMethods . 然后,您将编写一个控制器类,该类具有向其传递BackgroundWorkerICommonUiMethods

Inside the controller's constructor, subscribe to the appropriate background worker events. 在控制器的构造函数中,订阅适当的后台工作程序事件。

In the controller's implementation for the handlers for those events, call the appropriate methods of the ICommonUiMethods passed to the constructor. 在这些事件的处理程序的控制器实现中,调用传递给构造函数的ICommonUiMethods的适当方法。

Your first option depends on what are the responsibilities of your classes. 您的第一选择取决于您的课程的职责。 Although I doubt that they represent a is a relationship. 尽管我怀疑它们代表的是一种关系。 One of quite common guidelines is that in general you should avoid inheritance if you can . 相当普遍的准则之一是, 如果可以的话 ,通常应该避免继承

I'd also advice against the second option - reasons the same as above. 我也建议不要第二种选择-原因与上述相同。

Your third choice seems the best option - after all, it's exactly what you want: one standard place of creating a background worker. 您的第三选择似乎是最好的选择-毕竟,这正是您想要的: 创建后台工作人员的一个标准位置。 So a concept of a factory is exactly what you need. 因此, 工厂概念正是您所需要的。 You can also provide or configure delegate callbacks this way, so there will be even less duplication (even the last two lines you've mentioned). 您还可以通过这种方式提供或配置委托回调,因此重复的次数将更少(甚至您提到的最后两行)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM