![](/img/trans.png)
[英]How do I pass an argument to an event handler when the event handler is a delegate and doesn't include that argument?
[英]How to pass a delegate as an argument to subscribe as an event handler?
我有一個提供事件StkQuit
的外部應用程序。
我在靜態類中訂閱此事件,該類處理我的應用程序和[外部]應用程序之間的所有通信。 我想使用另一個位於我的表單類的處理程序訂閱StkQuit
事件。
此處理程序將通知用戶外部應用程序已關閉。 我想在名為SubscribeToStkQuit
的靜態類中有一個泛型方法,它接受委托作為參數,並將該委托(指我的表單類中的處理程序) StkQuit
到StkQuit
事件。
這可能嗎? 這是實現此類功能的最優雅/最簡單的方法嗎?
我的示例代碼:
表格類
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;
}
[更新]
根據評論,我已更新代碼,如下所示:
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");
}
我仍然得到演員異常。 有任何想法嗎 ??
[更新#2]
我仍然遇到這個問題。 在我的靜態類中,當OnQuit
觸發時,我已經有了一個處理程序:
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)
{
// handle this
}
}
private static void StkQuit()
{
_stkUiApplication.OnQuit -= StkQuit;
Marshal.FinalReleaseComObject(_stkUiApplication);
Marshal.FinalReleaseComObject(_stkRoot);
}
這很好用。 所以我想我會為_stkUiApplication創建一個公共屬性,並以相同的方式從表單類訂閱:
靜態類
public static AgUiApplication StkUiApplication
{
get { return _stkUiApplication; }
}
表格類
private void SubscribeToStkQuit()
{
UtilStk.StkUiApplication.OnQuit += StkQuit;
}
private void StkQuit()
{
MessageBox("TEST");
}
如果使用實例方法訂閱靜態事件,則在處理靜態事件之前不會對實例進行垃圾回收(除非您取消訂閱)。
這將導致內存泄漏。
除此之外,你的代碼的問題是,簽名ForceClose()
不匹配_stkUiApplication.OnQuit
它需要ForceClose(object sender, SomeKindOfEventArgs e)
它應該是UtilStk.SubscribeToStkQuit(forceClose => (s, e){ForceClose();});
編輯:
您對外部應用的引用是靜態的:
private static AgUiApplication _stkUiApplication;
所以它會在你的申請期間存在。 添加事件處理程序
_stkUiApplication.OnQuit
將引用傳遞給表單類實例上的方法。 此引用現在將在您的應用程序的生命周期中保留,因此不能進行垃圾回收。
要處理這種情況,要么在處理偵聽對象時顯式取消注冊( - =)處理程序,要么使用靜態處理程序處理靜態事件。
我錯誤地認為你最初是在描述網絡表單,這會改變一些事情(你可能只會實例化一個Form
),但無論如何都是如此。 這是一個很好的做法。
要解決當前問題:您需要輸入傳遞給的參數:
public static void SubscribeToStkQuit(Delegate subscribeHandler)
{
_stkUiApplication.OnQuit += subscribeHandler;
}
是_stkUiApplication.OnQuit
的類型
就像是
public static void SubscribeToStkQuit(EventHandler<EventArgs> subscribeHandler)
{
_stkUiApplication.OnQuit += subscribeHandler;
}
然后你可以這樣做:
public void SubscribeToStkQuit()
{
UtilStk.SubscribeToStkQuit((sender, args) => ForceClose(sender, args));
}
是的你可以!
但最好使用動作和函數,這些參數化在參數化方面都很靈活(所有這些都在System命名空間中)。
無論如何,我還有另一個建議:你為什么不使用事件訪問器? 您可以在靜態類中創建一個:
public event EventHandler Quit { add { _stkUiApplication.OnQuit += value; } remove { _stkUiApplication.OnQuit -= value; } }
關於操作和函數,這些也是委托,因此您可以將它們作為任何委托的輸入參數隨處使用。
也許您可以使用事件訪問器並以.NET方式執行,不是嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.