如何将代理作为参数传递给订阅作为事件处理程序? [英] How to pass a delegate as an argument to subscribe as an event handler?

查看:93
本文介绍了如何将代理作为参数传递给订阅作为事件处理程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个提供事件的外部应用程序 - StkQuit 。我在一个处理我的应用程序和外部应用程序之间的所有通信的静态类中订阅了这个事件。我想使用位于我的表单类的另一个处理程序订阅 StkQuit 事件。该处理程序将通知用户外部应用程序已关闭。为了保持一定程度的正交性,我想在一个名为'SubscribeToStkQuit'的静态类中使用一个通用的方法,它接受一个委托作为一个参数,并将该委托(指我的表单类的处理程序)订阅到 StkQuit 事件。这可能吗?这是实现这种功能的最优雅/简单的方法吗?

I have an external application that provides an event - StkQuit. I subscribe to this event in a static class that handles all communication between my application and the external application. I would like to subscribe to the StkQuit event using another handler that sits on my form class. This handler will inform the user that the external application has been closed. To keep a certain level of orthogonality, I would like to have a generic method in the static class called 'SubscribeToStkQuit' that accepts a delegate as a parameter and subscribes that delegate (referring to the handler on my form class) to the StkQuit event. Is this possible? Is this the most elegant/simplistic way to achieve such functionality?

表单类

public delegate void dForceClose();
public void SubscribeToStkQuit(dForceClose forceClose)
{
    UtilStk.SubscribeToStkQuit(forceClose = new dForceClose(ForceClose));
}
private void ForceClose()
{
    MessageBox.Show("TEST");
}

静态类

private static AgUiApplication _stkUiApplication;
public static void SubscribeToStkQuit(Delegate subscribeHandler)
{
    _stkUiApplication.OnQuit += subscribeHandler;          
}

[更新]

根据评论,我已经更新了这样的代码:

As per comments I have updated the code like so:

public delegate void dForceClose(object sender, EventArgs e);
public void SubscribeToStkQuit(dForceClose forceClose)
{
    UtilStk.SubscribeToStkQuit(forceClose = new dForceClose(ForceClose));
}
private void ForceClose(object sender, Eventargs e)
{
    MessageBox.Show("TEST");
}

我还在收到投放异常。任何想法?

I am still getting the cast exception. Any ideas ??

[更新]

我还有问题有了这个。在我的静态类中,我有一个处理程序已经在OnQuit触发时处理。像这样:

I'm still having problems with this. In my static class I have a handler already for disposing when OnQuit fires. Like so:

private static AgUiApplication _stkUiApplication;

public static bool CheckThatStkIsAvailable()
{
    object stkApplication = null;

    try
    {
        stkApplication = Marshal.GetActiveObject(_stkProgId);
        _stkUiApplication = stkApplication as AgUiApplication;
        _stkUiApplication.OnQuit += StkQuit;
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}

private static void StkQuit()
{
    _stkUiApplication.OnQuit -= StkQuit;
    Marshal.FinalReleaseComObject(_stkUiApplication);
    Marshal.FinalReleaseComObject(_stkRoot);
}

这工作正常。所以我以为我会为_stkUiApplication创建一个公共属性,并以相同的方式从表单类订阅。像这样:

This works fine. So I thought I would create a public property for _stkUiApplication and subscribe from the form class in the same manner. Like so:

静态类

public static AgUiApplication StkUiApplication
{
    get { return _stkUiApplication; }
}

表单类

private void SubscribeToStkQuit()
{
    UtilStk.StkUiApplication.OnQuit += StkQuit;
}

private void StkQuit()
{
    MessageBox("TEST");
}

这似乎还不行。使用对象发件人,Eventargs e使我感到困惑..这里是事件委托签名:

This still doesn't seem to work. Using "object sender, Eventargs e" is confusing me.. here is the event delegate signature:

public delegate void IAgUiApplicationEvents_OnQuitEventHandler();

我将阅读C#事件,处理和委托。整个事情让我感到困惑。

I'm going to read up on C# events, handling and delegates. The whole thing confuses me.

WulfgarPro

WulfgarPro

推荐答案

使用实例方法到静态事件,那么实例将不会被垃圾收集,直到静态事件被排除(除非你取消订阅)。

If you subscribe to a static event with an instance method, then the instance will not be garbage collected until the static event is disposed (unless you unsubscribe).

这将导致内存泄漏

除此之外,代码的问题是 ForceClose()的签名与 _stkUiApplication.OnQuit 它需要是 ForceClose(object sender,SomeKindOfEventArgs e)

Beyond that, the problem with your code is that the signature of ForceClose() does not match _stkUiApplication.OnQuit it needs to be ForceClose(object sender, SomeKindOfEventArgs e)

应该是 UtilStk.SubscribeToStkQuit(forceClose =>(s,e){ForceClose();});

编辑:

对外部应用程序的引用是静态的:

The reference to your external app is static:

private static AgUiApplication _stkUiApplication;

所以它将在您的应用程序的持续时间内生活。将事件处理程序添加到

so it will live for the duration of your application. Adding an event handler to

 _stkUiApplication.OnQuit

传递对表单类实例上的方法的引用。这个引用现在将在你的应用程序的使用期限内进行,所以它不能被垃圾回收。

passes a reference to a method on the instance of your form class. This reference will now be held for the life of your application, so it cannot be garbage collected.

为了处理这种情况,要么明确地取消注册( - =)处理侦听对象的处理程序,或使用静态处理程序处理静态事件。

To handle for this situation, either explicitly de-register (-=) the handler when the listening object is disposed, or handle static events with static handlers.

我错误地认为您首先描述Web表单,这会改变一些事情您可能只会实例化一个表单),但上述是否适用。这是很好的做法。

I mistakenly thought that you were describing web forms at first, which changes things a bit (you may only ever instantiate one Form), but the above holds true regardless. And it is good practice.

解决您当前的问题:
您需要输入传递给的参数:

To solve your current problem: You need to type the parameter passed to:

public static void SubscribeToStkQuit(Delegate subscribeHandler)
{
    _stkUiApplication.OnQuit += subscribeHandler;          
}

_stkUiApplication.OnQuit

to be the type of _stkUiApplication.OnQuit

public static void SubscribeToStkQuit(EventHandler<EventArgs> subscribeHandler)
{
    _stkUiApplication.OnQuit += subscribeHandler;          
}

然后你可以这样做:

public void SubscribeToStkQuit()
{
    UtilStk.SubscribeToStkQuit((sender, args) => ForceClose(sender, args));
}

这篇关于如何将代理作为参数传递给订阅作为事件处理程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆