C# 编写一个接受两种不同类型EventHandler的方法

C# 编写一个接受两种不同类型EventHandler的方法,c#,event-handling,overloading,C#,Event Handling,Overloading,我已经写了这些扩展方法,我想把它们浓缩成一个,因为它们有效地做了完全相同的事情。我遇到的问题是无法将HtmlElementEventHandler作为EventHandler参数传入 public static async Task WaitUntilAsync (this Action action, Action<EventHandler> addHandler, Action<EventHandler> removeHandl

我已经写了这些扩展方法,我想把它们浓缩成一个,因为它们有效地做了完全相同的事情。我遇到的问题是无法将HtmlElementEventHandler作为EventHandler参数传入

    public static async Task WaitUntilAsync
        (this Action action, Action<EventHandler> addHandler,
        Action<EventHandler> removeHandler, Predicate<string> pred)
    {
        var t = new TaskCompletionSource<bool>();

        System.EventHandler handler = new System.EventHandler((s, e) => 
            {
                if (pred((s as MyAsyncWebBrowser).DocumentTitle))
                    t.SetResult(true);
            });

        addHandler(handler);

        action();
        await t.Task;

        removeHandler(handler);
    }

    public static async Task WaitUntilAsync
(this Action action, Action<System.Windows.Forms.HtmlElementEventHandler> addHandler,
Action<System.Windows.Forms.HtmlElementEventHandler> removeHandler, Predicate<string> = h => true)
    {
        var t = new TaskCompletionSource<bool>();

        System.Windows.Forms.HtmlElementEventHandler handler = new System.Windows.Forms.HtmlElementEventHandler((s, e) =>
        {
            if (pred)
                t.TrySetResult(true);
        });

        addHandler(handler);

        action();
        await t.Task;

        removeHandler(handler);
    }
公共静态异步任务WaitUntilAsync
(此操作,操作addHandler,
动作removeHandler,谓词pred)
{
var t=new TaskCompletionSource();
System.EventHandler=新的System.EventHandler((s,e)=>
{
if(pred((作为MyAsyncWebBrowser.DocumentTitle))
t、 SetResult(true);
});
addHandler(handler);
动作();
等待任务;
移除处理器(处理器);
}
公共静态异步任务WaitUntilAsync
(此操作,操作addHandler,
动作removeHandler,谓词=h=>true)
{
var t=new TaskCompletionSource();
System.Windows.Forms.HtmlElementEventHandler处理程序=新的System.Windows.Forms.HtmlElementEventHandler((s,e)=>
{
if(pred)
t、 TrySetResult(真);
});
addHandler(handler);
动作();
等待任务;
移除处理器(处理器);
}
有什么想法吗

以前的尝试

    public static async Task WaitUntilAsync<TDelegate>
        (this Action action, Action<TDelegate> addHandler,
        Action<TDelegate> removeHandler, Predicate<string> pred)
    {
        var t = new TaskCompletionSource<bool>();

        TDelegate handler = (s, e) =>
        {
            if (pred((s as MyAsyncWebBrowser).DocumentTitle))
                t.SetResult(true);
        };

        addHandler(handler);

        action();
        await t.Task;

        removeHandler(handler);
    }
公共静态异步任务WaitUntilAsync
(此操作,操作addHandler,
动作removeHandler,谓词pred)
{
var t=new TaskCompletionSource();
TDelegate处理程序=(s,e)=>
{
if(pred((作为MyAsyncWebBrowser.DocumentTitle))
t、 SetResult(true);
};
addHandler(handler);
动作();
等待任务;
移除处理器(处理器);
}

这让我“无法将Lambda表达式转换为委托类型,因为它不是委托类型。”在开始时。

请尝试将此作为您的定义。我喜欢仿制药

public static async Task WaitUntilAsync<T>(this Action action, Action<T> addHandler, Action<T> removeHandler, Predicate<string> pred) where T : class
公共静态异步任务WaitUntilAsync(此操作、操作addHandler、操作removeHandler、谓词pred),其中T:class
不幸的是,不能将委托用作一般约束,例如:

public static async Task WaitUntilAsync<T>(this Action action, Action<T> addHandler, Action<T> removeHandler, Predicate<string> pred) where T : EventHandler
公共静态异步任务WaitUntilAsync(此操作、操作addHandler、操作removeHandler、谓词pred),其中T:EventHandler
…因此,您必须使用反射来确认您的类型,然后手动强制转换它

下面是一个完整的示例:

  public static async Task WaitUntilAsync<TDelegate>(this Action action, Action<TDelegate> addHandler, Action<TDelegate> removeHandler, Predicate<string> pred) where TDelegate : class
    {
        var delegateType = typeof(TDelegate);

        if (delegateType != typeof(EventHandler) && !delegateType.IsSubclassOf(typeof(EventHandler))) throw new Exception("TDelegate must be EventHandler or a subclass.");

        var t = new TaskCompletionSource<bool>();

        EventHandler realHandler = (sender, args) =>
        {
            //do real event work here
        };

        var handler = Delegate.CreateDelegate(delegateType, realHandler.Method) as TDelegate;

        addHandler(handler);

        action();
        await t.Task;

        removeHandler(handler);
    }
public静态异步任务WaitUntilAsync(此操作、操作addHandler、操作removeHandler、谓词pred),其中TDelegate:class
{
var delegateType=类型(TDelegate);
if(delegateType!=typeof(EventHandler)&&!delegateType.IsSubclassOf(typeof(EventHandler)))抛出新异常(“TDelegate必须是EventHandler或子类”);
var t=new TaskCompletionSource();
EventHandler realHandler=(发送方,参数)=>
{
//这里有真正的活动吗
};
var handler=Delegate.CreateDelegate(delegateType,realHandler.Method)作为TDelegate;
addHandler(handler);
动作();
等待任务;
移除处理器(处理器);
}

我忘了提到我尝试使用泛型,但失败了。。。我遇到了一些奇怪的代理演员错误。。。我相信你刚刚发现:/…什么演员错误?正如我提到的,您不能将泛型约束到委托,但有一个解决方法。如果您要将处理程序转换为t,您不能显式转换它,但您不希望在它失败的情况下转换它。您可以这样做:var convertedHandler=handler as T。然后,检查它是否为null,如果为null,则抛出异常。否则,请在addHandler()和removeHandler()调用中使用该新值。请确保添加“where T:class”作为通用约束以使其生效。需要进行空检查以确认转换成功。我将更新我的答案,以包含完整的函数定义。发布完整的示例。此问题与以下问题几乎是重复的: