[英]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.