如何使用带有接口的 child class 委托的事件处理程序

How to use event handler with delegate from child class with interface

我在这里进行了一些搜索,但未能得到我的问题的明确答案。 我有几个 child classes 都有 1 个接口。我有一个 parent class 包含一个变量,这个变量是根据外部参数创建的 child classes 之一的新实例。这是一些代码:

public interface I
{
    public delegate void ExecutionCompletedHandler(bool status);
    public event ExecutionCompletedHandler executionCompleted;
    public void Execute();
}

public class C1 : I
{
    public void Execute()
    {
        // Create background worker and execute DoStuff
    }

    public void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        bool status = (bool)e.Result;
        this.executionCompleted(true);
    }
}

public class C2 : I
{
    // Same setup as C1
}

public class C3 : I
{
    // Same setup as C1
}

public class MyManager
{
    public void doStuff(int val)
    {
        var compObj = null;
        // compObj is now instantiated as new instance of C1, C2 or C3 depending on val
        // ex: compObj = new C1();

        compObj.executionCompleted += new I.ExecutionCompletedHandler(executionCompletedHandler);
        compObj.Execute();
    }

    private void executionCompletedHandler(bool status)
    {
        // Do stuff with status and exit gracefully
    }
}

这是我想做的,但我知道这是不对的。我觉得我已经完成了 90%。它是说 C1 class 中的 executionCompleted 变量隐藏了接口的变量。我尝试遵循各种指南和示例,但一直无法弄清楚。谢谢!

编辑:我在 Visual Studio 2010 年使用 .NET 4.0。

编辑 2: 在@NikProtsman 的帮助下,我能够弄清楚...我将接口转换为抽象 class,并在该抽象 class 中实现了 CompleteExecution 函数。在此函数中,我将调用事件处理程序。在 C1/C2/C3 classes 中,当后台 worker 完成执行时,我会调用此方法。完美运行。我们正在升级到 VS 2019,在此之后,我将推动它更快地实现!谢谢!

试试这个:

在您的界面中,将执行更改为:

public Task Execute();

在你的 Class C1:

//Add this line to conform to Interface
public event I.ExecutionCompleteHandler executionCompleted;

public async Task Execute()
{
    // Create background worker and execute DoStuff
    await DoStuff();
    // You'll need to supply appropriate args here
    BackgroundWorkerCompleted(this, args);
}

public void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    bool status = (bool)e.Result;
    //Changed this line, assumed you needed the status from the line above
    executionCompleted?.invoke(status);
}

接下来你的 MyManager 应该是这样的:

public class MyManager
{
    public async Task doStuff(int val)
    {
        var compObj = null
        // compObj is now instantiated as new instance of C1, C2 or C3 depending on val
        compObj = new C1();

        // Subscribe to the 'executioncompleted' event in your new instance
        compObj.executionCompleted += HandleExecutionComplete;
        // Execute your code
        await compObj.Execute();
        // Unsubscribe from the event (cleaning up after yourself)
        compObj.executionCompleted -= HandleExecutionComplete;
    }

    private void HandleExecutionComplete(bool status)
    {
        // Do stuff with status and exit gracefully
    }
}

这里的关键点是在您的管理器中正确分配执行处理程序,然后使用它来订阅 C1 class 事件。在 C1 class 中,为 DoStuff 使用一个 Task,并在 Execute 中等待它成为一个异步任务。一旦 DoStuff 完成,WorkerCompleted 任务就会运行,执行您的处理程序,然后您就可以开始了。

这都可以稍微简化,但这超出了这个问题的范围。这个想法是控制流将如何工作,并使用带有等待的异步调用来确保您的程序等待它需要的东西,然后继续,以及您如何在外部订阅该事件。

一定要在外面等待您的 MyManager.doStuff 电话,否则您等待的任何结果都不会及时得到。