C# 关于事件

关于事件

要了解事件的机制,首先要明白委托的机制。事件机制主要分为事件的声明,事件的触发,事件的响应。事件的触发者成为“发布者”,事件的响应者成为事件的“订阅者”

事件特征:
发行者确定何时引发事件,订户确定执行何种操作来响应该事件。
一个事件可以有多个订户。 一个订户可处理来自多个发行者的多个事件。
没有订户的事件永远也不会引发。
事件通常用于通知用户操作,例如,图形用户界面中的按钮单击或菜单选择操作。
如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。 要异步调用事件,请参见使用异步方式调用同步方法。
在 .NET Framework 类库中,事件是基于 EventHandler 委托和 EventArgs 基类的。


事件的发布和订阅:
事件的发布类中一般包括事件的声明,事件的激发(其实也就是响应,但是响应函数中一定要用到委托)。事件的订阅者要用事件发布类的变


量(用来指定委托对应的函数),事件响应函数。示例:
class Publish
    {
        public event EventHandler eventName; //declare event named eventName


        public void inspireEvent()           // inspire the event
        {
            onEventName(new EventArgs());
        }


        public void onEventName(EventArgs e) // will use the scriber's method to reply the event
        {
            EventHandler handle = eventName;
            if (handle != null)
            {
                handle(this,e);
            }
        }
    }


class Scriber
    {
        public Scriber(Publish pb)
        {
            pb.eventName += howDo; // scribe the event
        }


        public void howDo(Object sender, EventArgs e)
        {
            Console.WriteLine("what a fuck day it is");
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            Publish ph = new Publish();
            Scriber sb = new Scriber(ph);


            ph.inspireEvent();		//motivate the event
        }
    }

事件的独特性:
事件是委托,但是它是特殊的委托, 调用事件只能在声明事件的类中,在事件的派生类中不能出现诸如:
EventHandler handle = eventBase;
eventBase(obj,e);
只能出现 eventBase+=,eventBase-=。
所以如果要调用基类中的事件只能通过间接的方式,示例如下:
 class BaseEvent
    {
        public event EventHandler baseEvent;


        public virtual void draw()
        {
            Console.WriteLine("This is in base draw");
        }


        public virtual void onDraw(EventArgs e)
        {
            EventHandler handle = baseEvent;
            if (handle != null)
            {
                handle(this ,e);
            }
            Console.WriteLine("this is in base on");
        }
    }


class Derived : BaseEvent
    {
        public override void draw()
        {
            //base.draw();
            Console.WriteLine("this is in derived class");
        }


        public override void onDraw(EventArgs e)
        {
            //EventHandler handle = baseEvent;
            //baseEvent(this, e);


            base.onDraw(e);
            
        }


        public void motivateDraw()
        {
            onDraw(new EventArgs());
        }
    }


class Scribe
    {
        public Scribe(Derived dr)
        {
            dr.baseEvent += Motive;
        }


        public void Motive(Object sender, EventArgs e)
        {
            Console.WriteLine("what a fuck day");
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            Derived D = new Derived();
            BaseEvent B = new BaseEvent();
            Scribe Sb = new Scribe(D);
            D.motivateDraw();
        }
    }

接口事件的实现:
接口事件的实现和接口中方法,属性的实现基本相同。当订阅事件的时候,订阅的方法通过事件访问器添加到委托的方法列表中,事件访问器类似于属性访问器,不过访问器被命名为add,remove。在大多数情况下都不需要自定义事件访问器,因为编译器会帮我们制定,但是当编译器不能帮我们制定的时候,我们就得自己去写事件访问器了。当多个接口中含有具有相同签名的事件的时候,这个时候就得使用事件的显示定义了,并且在事件的订阅的时候使用接口来调用(这里很类似属性,索引器,方法),示例如下:
namespace ConsoleApplication16InterfaceEvent
{
    interface Iface
    {
        event EventHandler faceEvent;
    }


    interface Ifoot
    {
        event EventHandler footEvent;
    }


    interface Ihand
    {
        event EventHandler footEvent;
    }
    class InterEvent : Iface,Ifoot,Ihand
    {
        public event EventHandler faceEvent;
        //public event EventHandler footEvent;
        public event EventHandler preFootEvent;
        public event EventHandler nexHandEvent;


        Object objectLock = new Object();


        event EventHandler Ifoot.footEvent
        {
            add 
            {
                lock (objectLock)
                {
                    preFootEvent += value;
                }
            }
            remove
            {
                lock (objectLock)
                {
                    preFootEvent -= value;
                }
            }
        }


        event EventHandler Ihand.footEvent
        {
            add 
            {
                lock (objectLock)
                {
                    nexHandEvent += value;
                }
            }


            remove
            {
                lock (objectLock)
                {
                    nexHandEvent -= value;
                }
            }
        }


        public void finger()
        {
            EventHandler handle = preFootEvent;
            if ( handle != null)
                preFootEvent(this,new EventArgs());


            handle = nexHandEvent;
            if (handle != null)
                nexHandEvent(this,new EventArgs());
        }
    }


}


//...............
namespace ConsoleApplication16InterfaceEvent
{
    class Scribe
    {
        public Scribe(InterEvent Et)
        {
            Ifoot foot = (Ifoot)Et;
            foot.footEvent += draw1;


            Ihand hand = (Ihand)Et;
            hand.footEvent += draw2;


            
        }


        void draw1(Object sender, EventArgs e)
        {
            Console.WriteLine("this is in Scribe draw1");
        }


        void draw2(Object sender, EventArgs e)
        {
            Console.WriteLine("this is in Scribe draw2");
        }
    }
}


//..................
namespace ConsoleApplication16InterfaceEvent
{
    class Program
    {
        static void Main(string[] args)
        {
            InterEvent EI = new InterEvent();
            Scribe Sb = new Scribe(EI);
            EI.finger();
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值