C# 如何将委托作为参数传递给订阅作为事件处理程序?
我有一个外部应用程序,它提供一个事件C# 如何将委托作为参数传递给订阅作为事件处理程序?,c#,events,delegates,C#,Events,Delegates,我有一个外部应用程序,它提供一个事件StkQuit 我在一个静态类中订阅此事件,该类处理我的应用程序和外部应用程序之间的所有通信。我想使用表单类上的另一个处理程序订阅StkQuit事件 此处理程序将通知用户外部应用程序已关闭。我希望在静态类中有一个名为SubscribeToStkQuit的泛型方法,该方法接受委托作为参数,并将该委托(指我表单类上的处理程序)订阅到StkQuit事件 这可能吗?这是实现此类功能的最优雅/最简单的方式吗 我的示例代码: 表单类 public delegate voi
StkQuit
我在一个静态类中订阅此事件,该类处理我的应用程序和外部应用程序之间的所有通信。我想使用表单类上的另一个处理程序订阅StkQuit
事件
此处理程序将通知用户外部应用程序已关闭。我希望在静态类中有一个名为SubscribeToStkQuit
的泛型方法,该方法接受委托作为参数,并将该委托(指我表单类上的处理程序)订阅到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 static AgUiApplication StkUiApplication
{
get { return _stkUiApplication; }
}
private void SubscribeToStkQuit()
{
UtilStk.StkUiApplication.OnQuit += StkQuit;
}
private void StkQuit()
{
MessageBox("TEST");
}
静态类
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 static AgUiApplication StkUiApplication
{
get { return _stkUiApplication; }
}
private void SubscribeToStkQuit()
{
UtilStk.StkUiApplication.OnQuit += StkQuit;
}
private void StkQuit()
{
MessageBox("TEST");
}
[更新]
根据评论,我已将代码更新如下:
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);
}
这个很好用。所以我想我应该为40; u stkuiaapplication)创建一个公共属性并以相同的方式从form类中订阅:
静态类
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 static AgUiApplication StkUiApplication
{
get { return _stkUiApplication; }
}
private void SubscribeToStkQuit()
{
UtilStk.StkUiApplication.OnQuit += StkQuit;
}
private void StkQuit()
{
MessageBox("TEST");
}
表单类
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 static AgUiApplication StkUiApplication
{
get { return _stkUiApplication; }
}
private void SubscribeToStkQuit()
{
UtilStk.StkUiApplication.OnQuit += StkQuit;
}
private void StkQuit()
{
MessageBox("TEST");
}
如果使用实例方法订阅静态事件,则在释放静态事件之前,不会对该实例进行垃圾收集(除非取消订阅) 这将导致内存泄漏 除此之外,代码的问题在于
ForceClose()
的签名与\u stkuiaapplication不匹配。在退出时
必须是ForceClose(对象发送方,某种目标方)
它应该是UtilStk.SubscribeToStkQuit(forceClose=>(s,e){forceClose();})代码>
编辑:
对外部应用程序的引用是静态的:
private static AgUiApplication _stkUiApplication;
因此,它将在您的应用程序期间有效。将事件处理程序添加到
_stkUiApplication.OnQuit
传递对窗体类实例上的方法的引用。此引用现在将在应用程序的生命周期内保留,因此不能对其进行垃圾收集
要处理这种情况,请在释放侦听对象时显式取消注册(-=)处理程序,或者使用静态处理程序处理静态事件
我错误地认为您一开始是在描述web表单,这稍微改变了一些事情(您可能只实例化了一个表单
),但不管怎样,上面的内容都是正确的。这是一个很好的实践
要解决您当前的问题,请执行以下操作:
您需要键入传递给以下对象的参数:
public static void SubscribeToStkQuit(Delegate subscribeHandler)
{
_stkUiApplication.OnQuit += subscribeHandler;
}
要成为\u stkuiaapplication.OnQuit的类型
差不多
public static void SubscribeToStkQuit(EventHandler<EventArgs> subscribeHandler)
{
_stkUiApplication.OnQuit += subscribeHandler;
}
是的,你可以
但是最好使用动作和函数,它们在参数化方面是灵活的(它们都在系统名称空间中)
无论如何,我还有另一个建议:为什么不使用事件访问器呢?您可以在静态类中创建一个:
public event EventHandler Quit { add { _stkUiApplication.OnQuit += value; } remove { _stkUiApplication.OnQuit -= value; } }
关于操作和函数,它们也是委托,因此您可以在任何地方使用它们作为任何委托的输入参数
也许您可以使用事件访问器并以.NET的方式进行访问,不是吗 这看起来非常优雅/简单…你不喜欢哪一部分?@Cpfohl-\u stkuiaapplication.OnQuit+=subscribebhandler代码>抛出“无法将类型“System.Delegate”隐式转换为“AGI.Ui.Application.IAgUiApplicationEvents\u OnQuitEventHandler”…”,因此我将委托转换为上述类型,并得到一个运行时异常“无法将类型为dForceClose的对象转换为类型AGI.Ui.Application.IAgUiApplicationEvents\u OnQuitEventHandler”。有什么想法吗?(对不起!我没有仔细看),但请看一下@CrapHands的答案。他发现了这个问题。所有.NET事件都必须具有“object sender,EventArgs e”签名。我只是重申一下,我认为你不应该像那样连接到事件,你会泄漏内存。最好的办法是将事件连接到Global.asax中的另一个静态事件,或者在某个地方运行一次代码。执行此操作:UtilStk.OnQuit+=(发送方,参数)=>SomeClassInMyApp.TheStaticMethodToHandleIt();是否适合在实例方法本身中取消订阅-=
代码>不是静态的。静态方法SubscribeToStkQuit
用于分配作为实例方法的处理程序。你能不能再解释一下内存泄漏,这样我就能理解:D?出于某种原因,lambda表达式在将“objectsender,Eventargs args”传递到ForceClose时给我带来了问题。我的行是这样的:UtilStk.SubscribeToStkQuit((sender,e)=>ForceClose(objectsender,EventArgs e))代码>-我看不出我的和你的有什么区别?@WulfgarPro应该更明确一些。当我说类似的话时,我的意思是您需要找到事件args的实际类型。将鼠标悬停在VS中的_stkuiaapplication.OnQuit上,找出它的实际类型,并用它替换这里的类型。另外,UtilStk.SubscribeToStkQuit((发送方,参数)=>ForceClose(对象发送方,事件参数));应该是UtilStk.SubscribeToStkQuit((发送方,参数)=>ForceClose(发送方,参数));