从拥有类外部调用C#事件?

在任何情况下是否有可能实现这一目标?

我现在的情况如下:

public class CustomForm : Form { public class CustomGUIElement { ... public event MouseEventHandler Click; // etc, and so forth. ... } private List _elements; ... public void CustomForm_Click(object sender, MouseEventArgs e) { // we might want to call one of the _elements[n].Click in here // but we can't because we aren't in the same class. } } 

我的第一个想法是有一个类似的function:

 internal enum GUIElementHandlers { Click, ... } internal void CustomGUIElement::CallHandler(GUIElementHandler h, object[] args) { switch (h) { case Click: this.Click(this, (EventArgs)args[0]); break; ... // etc and so forth } } 

这是一个非常难看的kludge,但它应该工作……虽然必须有一个更优雅的解决方案? .NET库一直使用消息处理程序和Control中的调用事件来执行此操作。 还有其他人有其他/更好的想法吗?

您只需添加一个公共方法来调用该事件。 Microsoft已针对某些事件执行此操作,例如PerformClick用于公开Click事件的控件。

 public class CustomGUIElement { public void PerformClick() { OnClick(EventArgs.Empty); } protected virtual void OnClick(EventArgs e) { if (Click != null) Click(this, e); } } 

然后,您将在示例事件处理程序中执行以下操作…

 public void CustomForm_Click(object sender, MouseEventArgs e) { _elements[0].PerformClick(); } 

c#中的event关键字修改委托的声明。 它阻止直接分配给委托(您只能对事件使用+ =和 – =),并且它会阻止从类外部调用委托。

所以你可以改变你的代码看起来像这样:

 public class CustomGUIElement { ... public MouseEventHandler Click; // etc, and so forth. ... } 

然后你可以像这样从类外部调用事件。

 myCustomGUIElement.Click(sender,args); 

缺点是使用该类的代码可以使用以下代码非常容易地覆盖任何已注册的处理程序:

 myCustomGUIElement.Click = null; 

如果将Click委托声明为事件,则不允许这样做。

你真的应该在方法中包装你想要能够从外部执行的代码。 然后,该方法可以执行您的事件所做的任何事情 – 该事件也会调用该方法。