注册一个处理程序对当前类的事件有一个自定义委托 [英] Registering a handler for an event on the current class with a custom delegate

查看:75
本文介绍了注册一个处理程序对当前类的事件有一个自定义委托的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义我的类的事件,我想使该类事件处理程序的方法之一。

I defined an event on my class and I want to make one of the methods of the class a handler for the event.

这是我到目前为止

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;
        }
    }
}



我如何注册事件无需处理程序做的主?

How can I register the event handler without having to do it in Main?

推荐答案

有一个通过的如何发布符合.NET框架准则关于如何创建和使用事件的更多信息事件。这个例子没有很明确的,因为它应该是这样,我会经过这里的过程走。

Have a read through How to: Publish Events that Conform to .NET Framework Guidelines for more information on how to create and use events. The example there isn't quite as clear as it should be so I'll walk through the process here.

定义一个事件所需的第一部分是将要使用的事件处理程序委托。它是要求所有谁愿意对本次活动收到通知的方法签名。您通常不必自己创建一个新的委托,就应该使用现有 事件处理程序 (或通用 事件处理程序和LT ; TEventArgs> )委托。你会使用非通用版本,如果你并不需要包括有关事件的任何其他参数。否则,你会使用通用的版本。根据你的情况,有没有必要对事件,这样你应该使用非通用事件处理程序

The first part needed to define an event is the event handler delegate to be used. It's the method signature that is required for all who wishes to receive notifications on this event. You generally don't have to create a new delegate yourself, you should use the existing EventHandler (or generic EventHandler<TEventArgs>) delegate. You'd use the non-generic version if you don't need to include any other arguments about the event. Otherwise you'd use the generic version. In your case, there aren't any other arguments needed about the event so you should use the non-generic EventHandler.

<子>(如果你想成为能够包括像旧值和新值作为参数,你会使用通用的版本从 EventArgs的。一个高级的话题了一点,所以我们将跳过这一点。)

(If you wanted to be able to include information like the old value and new value as arguments, you'd use the generic version with an appropriate class derived from EventArgs. A bit of an advanced topic so we'll skip that.)

第二天部分是定义该事件。这只是这么简单,如果你定义为你的类的属性。这里的区别在于,你会使用事件关键字指定要定义事件后,通过委托使用和事件的名称。命名事件改变性质的约定通常的格局, 属性名更改。既然你想被触发的事件时,名称属性改变,你应该将其命名为: NameChanged

The next part is to define the event. It's just as simple as if you were defining a property for your class. The difference here is that you'd use the event keyword to specify that you are defining an event followed by the delegate to use and the name of the event. The convention for naming the event for changing properties is usually in the pattern, PropertyNameChanged. Since you want an event that is fired when the Name property changes, you should name it: NameChanged.

public event EventHandler NameChanged;






这是可选的(但强烈建议)步骤是定义用于引发事件的方法。这将使它更容易为你,当你想引发事件。通常命名约定是类似于事件如何命名。这一次,事件名称 。所以,你会 OnNameChanged 这里命名。它通常被定义为这样的派生类可以很容易地覆盖该受保护的虚方法。到该函数的参数应该是所需要的事件的参数。由于这里有没有参数,也可能是没有留下签名中的参数。


An optional (but highly recommended) step is to define a method used to raise the event. This will make it easier for you to raise the event when you want. Usual naming convention is similar to how the event is named. This time, OnEventName. So you'd name it OnNameChanged here. It is usually defined as a protected virtual method that way derived classes could easily override this. The arguments to the function should be the arguments that is needed for the event. Since there are no arguments here, it could be left without arguments in the signature.

通过所有的地方,它只是一个调用事件处理程序的问题。这只是一个委托所以只是调用它。但是不要忘记检查,如果是第一,将意味着没有事件处理程序注册。给处理程序的参数应该是这个和任何(该所引发事件的对象)的参数应该的。在这种情况下,没有争论,但你应该返回的空 EventArgs的一个实例。

With that all in place, it's just a matter of calling the event handlers. It's just a delegate so just call on it. But don't forget to check if it's null first, that would signify that no event handlers were registered. The arguments to the handler should be this (the object that is raising the event) and whatever the arguments should be. In this case, there aren't arguments but you should return an instance of the "empty" 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());
    }
}






最后一部分是在你的属性,以这样组装起来。你想提高的情况下,如果转让将改变属性的值。很简单,只需要检查,看看是否旧值与新值不同。如果是,将其更改并引发事件。否则,什么也不做。


The final part is to wire this up in your properties. You'd want to raise the event if an assignment would change the value of the property. Pretty simple, just check to see if the old value is different from the new value. If it is, change it and raise the event. Otherwise, do nothing else.

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!!!
        }
    }
}






现在,我们已经设置完毕的情况下,要能够注册一些处理此事件。为了能够做到这一点,首先我们需要的实例,我们要等待名称的变化,我们需要一个事件处理方法,事件的正确的签名。该事件被定义为使用事件处理程序委托,所以我们需要用签名的方法:无效NameChanged(对象发件人,EventArgs五)。记住,发件人参数是引发事件的对象。在这种情况下,它是一个对象,所以我们可以得到改变了对象,并得到检查的属性,如果我们想。您可以命名此任何你想要的。我去为个人的模式是: 实例名 _ 事件名称 。因此,在这种情况下,我将其命名为: person_NameChanged


Now that we're all set with the event, you want to be able to register some handlers for this event. To be able to do this, first we'd need the instance of the Person that we want to wait for Name changes and we need a event handling method with the right signature for the event. The event is defined to use the EventHandler delegate so we need a method with the signature: void NameChanged(object sender, EventArgs e). Remember, the sender argument is the object that raised the event. In this case, it is a Person object so we can get the object that changed and get inspect the properties if we wanted to. You can name this whatever you want. The pattern I go for personally is: InstanceName_EventName. So in this case, I'd name it: 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
}



一旦被定义,添加处理程序的。事件我们会如果有什么变化通知

Once that is defined, add the handler to the event and we'll be notified if anything changes.

person.NameChanged += person_NameChanged;

如果你想要的处理程序类中是完全,你可以注册类中的事件。无需外部接线不起来。你可以从构造做到这一点。我不建议将您的代码到 OnNameChanged()事件提出的方法,该方法应预留只是引发事件。

If you wanted the handler to be completely within the class, you could register the event within the class. No need to wire it up externally. You could do it from the constructor. I would not suggest adding your code to the OnNameChanged() event raising method, that method should be reserved for simply raising the event.

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
}

请注意,在这个特殊的例子,该处理程序是静态的,所以它不依赖于一个实例。这将适用于任何一般。要知道,因为它是静态的,你将无法使用这个这也是为什么发件人投是必要的策略中。无论是静态或没有达到你最终,无论哪种方式应该罚款。

Note that in this particular example, the handler is static so it isn't tied to a single instance. It would work for any Person in general. Just be aware that since it is static, you would not be able to use this within the method which is why the cast on sender is necessary. Whether it is static or not is up to you ultimately, either way should be fine.

所以把这个一起,这是你能做什么:

So to put this all together, this is what you could do:

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";
    }
}

这篇关于注册一个处理程序对当前类的事件有一个自定义委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆