在运行时确定表单的身份(类型信息)

Determine form's identity (type information) at runtime

假设我有一个常见的 class 执行一些耗时的步骤(例如,将内容保存到 USB)。我希望能够从多种形式调用该代码,并在完成一个步骤时收到反馈。普通 class 如何知道向谁发送反馈?下面的代码描述了这种情况:

// ### Common class frmCommon ###
// Parent form (when feedback on some slow operation is required)
private static Form m_frmParent = null;

// ...
public static void SetParentForm(Form frmParent)
{
    // When some time consuming process takes place (such as saving to USB), setting the
    // parent form allows feedback to be given to the user (eg. as a progress bar)
    m_frmParent = frmParent;
}

public static void DoSomething()
{
    for (int nStep = 0; nStep < 100; nStep++)
    {
        // Tell the parent form how many product sets (groups of 20) there are to read
        if (m_frmParent != null)
        {
            // How to decide whether to call form 1 or form 2?
            ((frmForm1)m_frmParent).SendFeedback(nStep);
            ((frmForm2)m_frmParent).SendFeedback(nStep);
        }

        // Perform the time-consuming step...
        SlowStep(nStep);
    }
}

// ### FORM 1 frmForm1 ###
private void SomeEventForm1(int nStep)
{
    frmCommon.SetParentForm(this);
    frmCommon.DoSomething();
    frmCommon.SetParentForm(null);
}

public void SendFeedback(int nStep)
{
    // Do something like update a progress bar on form 1
    Application.DoEvents();
}

// ### FORM 2 frmForm2 ###
private void SomeEventForm2(int nStep)
{
    frmCommon.SetParentForm(this);
    frmCommon.DoSomething();
    frmCommon.SetParentForm(null);
}

public void SendFeedback(int nStep)
{
    // Do something like update a progress bar on form 2
    Application.DoEvents();
}

目标是 .NET 2.0,如果有影响的话。

调用代码必须向 class 提供委托。当 class 完成耗时过程后,它将调用该委托以通知调用代码它已完成。查看 here 以获得有关如何执行此操作的良好教程。

1 - 如果 SendFeedback 是您在两种形式中实现的函数,并且它们的作用相同,请考虑在 static class 到 [=31= 中创建单个 static 方法]扩展 Form:

public static class FormExtender
{
    public static void SendFeedback(this Form frm, int nStep)
   {
       //do what must be done
       //you can call this anyhere using, for instance: m_frmParent.SendFeedback(nStep)
       //when you call it like that, m_frmParent will be given to this function as the argument frm
   }

}

2 - 但是如果两种形式的方法不同,我建议你创建一个接口:

interface IFormWithFeedback
{
    void SendFeedback(int nStep);
}

然后 form1 和 form2 应该实现这个(只需在声明表单的地方添加 , IFormWithFeedBack):

public class frmForm1 : Form, IFormWithFeedback     
public class frmForm2 : Form, IFormWithFeedback

并且您在 class 中的父表单应该是 IFormWithFeedback 而不是表单:

 private static IFormWithFeedback m_frmParent = null;

这两个选项(扩展方法或接口)都允许您直接从 m_frmParent 调用 SendFeedback 而无需转换它。

我宁愿使用 事件:

public class SlowProcess {
  ...
  // Simplest, not thread safe
  public static event EventHandler<int> StepChanged;

  public static void DoSomething() {
    for (int nStep = 0; nStep < 100; nStep++) {
      if (null != StepChanged)
        StepChanged(null, nStep);

      SlowStep(nStep);
    } 
  }
}

...

public partial class MyEventForm: Form {
  ...    
  private void onStepChange(Object sender, int nStep) {
    //TODO: update form here after receiving a feedback 
  }

  private void TraceSlowProcess() {
    // feedback is required 
    SlowProcess.StepChanged += onStepChange;

    try {
      SlowProcess.DoSomething(); 
    }
    finally {
      // No need of feedback
      SlowProcess.StepChanged -= onStepChange;
    }
  }
}