[英]Registering a handler for an event on the current class with a custom delegate
我在我的 class 上定义了一个事件,我想让 class 的方法之一成为该事件的处理程序。
这是我到目前为止所拥有的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DelegatesAndEvents
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.NameChangeEventHandler += new Person.NameChangeEventHandlerDel;
p.Name = "Paul";
}
}
class Person
{
#region Events
public delegate void NameChangeEventHandlerDel(object sender, EventArgs args);
public event EventHandler NameChangeEventHandler;
protected void NameChange(EventArgs arg)
{
Console.WriteLine("Name change...");
}
#endregion
#region Properties
private string name;
public string Name
{
get { return name; }
set
{
NameChange(null);
name = value;
}
}
#endregion
public Person(string name = "John")
{
this.name = name;
}
}
}
如何注册事件处理程序而不必在 Main 中进行?
阅读如何:发布符合 .NET 框架指南的事件,了解有关如何创建和使用事件的更多信息。 那里的例子并不像它应该的那样清楚,所以我将在这里介绍整个过程。
定义事件所需的第一部分是要使用的事件处理程序委托。 这是所有希望接收有关此事件的通知的人都需要的方法签名。 您通常不必自己创建新委托,您应该使用现有的EventHandler
(或通用EventHandler<TEventArgs>
)委托。 如果您不需要包含有关该事件的任何其他 arguments,则可以使用非通用版本。 否则,您将使用通用版本。 在您的情况下,该事件不需要任何其他 arguments ,因此您应该使用非通用EventHandler
。
(如果您希望能够将诸如旧值和新值之类的信息包含为 arguments,则可以使用通用版本以及从EventArgs
派生的适当 class 。有点高级主题,所以我们将跳过它。)
下一部分是定义事件。 就像您为 class 定义一个属性一样简单。 这里的不同之处在于您将使用event
关键字来指定您正在定义一个事件,然后是要使用的委托和事件的名称。 Changed .更改属性的事件命名约定通常在模式 Changed
中。 由于您希望在Name
属性更改时触发一个事件,因此您应该将其命名为: NameChanged
。
public event EventHandler NameChanged;
一个可选(但强烈推荐)步骤是定义用于引发事件的方法。 这将使您更容易在需要时提出事件。 通常的命名约定类似于事件的命名方式。 .这一次, On
。 因此,您将在此处将其命名为OnNameChanged
。 它通常被定义为受保护的虚拟方法,派生类可以轻松地覆盖它。 arguments 到 function 应该是事件所需的 arguments。 由于此处没有 arguments,因此签名中可能没有 arguments。
一切就绪后,只需调用事件处理程序即可。 它只是一个代表,所以只需调用它。 但是不要忘记首先检查它是否是null
,这表示没有注册事件处理程序。 处理程序的 arguments 应该是this
(引发事件的 object)以及 arguments 应该是什么。 在这种情况下,没有 arguments 但您应该返回“空” EventArgs
的实例。
protected virtual void OnNameChanged()
{
EventHandler nameChanged = NameChanged; // always a good idea to store in a local variable
if (nameChanged != null)
{
nameChanged(this, new EventArgs());
}
}
最后一部分是将其连接到您的属性中。 如果分配会更改属性的值,您会想要引发事件。 很简单,只需检查旧值是否与新值不同。 如果是,请更改它并引发事件。 否则,别无他法。
private string name;
public string Name
{
get { return name; }
set
{
if (!String.Equals(value, name)) // if the value gets changed...
{
name = value;
OnNameChanged(); // raise the event!!!
}
}
}
现在我们已经设置好了事件,您希望能够为该事件注册一些处理程序。 为了能够做到这一点,首先我们需要要等待Name
更改的Person
实例,并且我们需要一个具有正确签名的事件处理方法。 该事件被定义为使用EventHandler
委托,因此我们需要一个带有签名的方法: void NameChanged(object sender, EventArgs e)
。 请记住, sender
参数是引发事件的 object。 在这种情况下,它是一个Person
object,因此我们可以获取已更改的 object,并根据需要检查属性。 你可以随意命名它。 _ .我个人的模式我 go 是: _
。 所以在这种情况下,我将其命名为: person_NameChanged
。
static void person_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender; // cast back to a Person so we can see what's changed
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name); // let's print the name
}
定义好之后,将处理程序添加到事件中,如果有任何变化,我们会收到通知。
person.NameChanged += person_NameChanged;
如果您希望处理程序完全位于 class 中,您可以在 class 中注册事件。 无需在外部接线。 你可以从构造函数中做到这一点。 我不建议将您的代码添加到OnNameChanged()
事件引发方法中,该方法应保留用于简单地引发事件。
public Person(string name = "John")
{
this.name = name;
this.NameChanged += builtin_NameChanged;
}
private static void builtin_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender; // cast back to a Person so we can see what's changed
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name); // let's print the name
}
请注意,在此特定示例中,处理程序是 static,因此它不绑定到单个实例。 它一般适用于任何Person
。 请注意,由于它是 static,因此您将无法在方法中使用this
,这就是为什么需要对发件人进行强制转换的原因。 是否是 static 最终取决于您,无论哪种方式都应该没问题。
所以把这一切放在一起,这就是你可以做的:
class Person
{
public Person(string name = "John")
{
this.name = name;
this.NameChanged += builtin_NameChanged;
}
public string Name
{
get { return name; }
set
{
if (!String.Equals(value, name))
{
name = value;
OnNameChanged();
}
}
}
public event EventHandler NameChanged;
protected virtual void OnNameChanged()
{
EventHandler nameChanged = NameChanged;
if (nameChanged != null)
{
nameChanged(this, new EventArgs());
}
}
private static void builtin_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender;
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name);
}
private string name;
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "Paul";
}
}
我更改并评论了您的代码,但我不确定您打算做什么:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DelegatesAndEvents
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
//here you have an event of type EventHandler and want to subscribe with a delegate of type
//NameChangeEventHandlerDel. This can't work. Furthermore you have to create the delegate passing
//a method.
//p.NameChangeEventHandler += new Person.NameChangeEventHandlerDel;
// this could be better (even if I'm not sure about the necessity to use an event,
//but it probably depends on what you really are trying to do):
p.NameChangeEventHandler += new EventHandler(p.NameChange);
p.Name = "Paul";
}
}
class Person
{
#region Events
// why do you define the delegate NameChangeEventHandlerDel and then declare the event of type EventHandler?
public delegate void NameChangeEventHandlerDel(object sender, EventArgs args);
public event EventHandler NameChangeEventHandler;
protected void NameChange(EventArgs arg)
{
Console.WriteLine("Name change...");
}
#endregion
#region Properties
private string name;
public string Name
{
get { return name; }
set
{
// here you should not call your method directly, but trigger the event (if this is what you want)
//i.e not: NameChange(null); but something like:
if (NameChangeEventHandler != null)
NameChangeEventHandler(this, null);
name = value;
}
}
#endregion
public Person(string name = "John")
{
this.name = name;
}
}
}
在您的人中调用一个方法并开始在该方法中引发事件。 每当人 class 引发事件时,因为主已订阅此事件。 您会收到 Main 的回电。
您刚刚订阅了该活动。 活动主体在哪里??
如果你 rem winforms 事件。 您订阅让我们说按钮单击事件,例如 btn_Click(object, eventArgs).. 然后您为这个事件方法提供一个主体,对吗? 这里也一样。
我真的不明白你的意图是什么,但是:
您尚未在将处理名称更改事件的程序 class 中订阅 function。
您尚未在 Person class 中触发事件。 你应该写:
protected void NameChange(EventArgs arg) { Console.WriteLine("名称更改..."); NameChangeEventHandler(); }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.