拿事件说那么一些事

.NET图像界面开发中最常见的一个事件大概就是按钮的clicked事件了,当点击图形界面的按钮时,就会调用一个与这个事件相关的方法对这个事件进行响应,做一些相关操作。但是事件并不局限于图像界面,也可能是满足程序的某个逻辑判断触发了事件。引发事件的对象叫做事件发送方,捕获事件并对其做出响应的对象叫做事件接收方。但是事件发送方并不知道哪个对象或者方法会处理它引发的事件,所以需要在事件发送方和事件接收方之间存在一媒介,明确某个对象或者某个类型的某个方法会对这个事件进行响应。.NET用委托作为事件发送方与事件接收方之间的媒介,委托只有一个签名,只要方法签名与委托签名匹配的方法,都可以声明自己对这个委托类型的事件的感兴趣,接收并处理它。

事件发送方的对象为了给事件接收对象传递一些额外信息,就需要写一个派生于System.EventArgs的类,封装一些数据。

    public class DrawEventArgs:EventArgs

    {

        private double m_Size;

        public DrawEventArgs(double size)

        {

            m_Size = size;

        }

        public double Size

        {

            get

            {

                return m_Size;

            }

        }

    }

下面声明一委托,该委托有两个参数,一个是参数代表事件的发送方,另一个是参数是该事件封装的数据。

public  delegate void ShapeSizeChanged(object sender,DrawEventArgs e);

ShapeSizeChanged的实例可以绑定到任何和它方法签名匹配的方法上。

下面是自定义事件委托,

public event ShapeSizeChanged SizeChanged;

下面是一个负责引发事件的类型代码,

    public class DrawManager

    {

        public event ShapeSizeChanged SizeChanged;

        protected void OnSizeChanged(DrawEventArgs e)

        {

            ShapeSizeChanged temp = SizeChanged;

            //是否有委托与该事件关联

            if (temp != null)

            {

                temp(this, e);

            }

        }

        public void SizeChange(double size)

        {

            DrawEventArgs e = new DrawEventArgs(size);

            OnSizeChanged(e);

        }

    }

而后定义两个监听事件的类型,

    public class Square

    {

        public Square(DrawManager drawManager)

        {

            //drawManager.SizeChanged += DrawSquare;

            //把事件关联到委托上

            drawManager.SizeChanged += new ShapeSizeChanged(DrawSquare);

        }

        public void DrawSquare(object sender, DrawEventArgs e)

        {

            Console.WriteLine(string.Format("The Square'Length = {0}", e.Size));

        }

        public void Detach(DrawManager drawManager)

        {

            //drawManager.SizeChanged -= DrawSquare;

            //解除事件和委托的关联

            drawManager.SizeChanged -= new ShapeSizeChanged(DrawSquare);

        }

    }

    public class Rectangle

    {

        public Rectangle(DrawManager drawManager)

        {

            drawManager.SizeChanged += DrawRectangle;

        }

        public void DrawRectangle(object sender, DrawEventArgs e)

        {

            Console.WriteLine(string.Format("The Rectangle'length={0} and width={1}.",e.Size*2,e.Size));

        }

        public void Detach(DrawManager drawManager)

        {

            drawManager.SizeChanged -= DrawRectangle;

        }

    }

测试代码,

    class Program

    {

        static void Main(string[] args)

        {

            DrawManager drawManager = new DrawManager();

            Rectangle rect = new Rectangle(drawManager);

            Square square = new Square(drawManager);

            //引发事件

            drawManager.SizeChange(5);

            //解除监听事件

            square.Detach(drawManager);

            drawManager.SizeChange(10);

            Console.ReadLine();

        }

    }

/*运行结果

  The Rectangle'length=10 and width=5.

  The Square'Length = 5

  The Rectangle'length=20 and width=10.

 */

.NET中的事件模式和观察者模式非常相似,也可谓是观察者模式在.NET下的进化版吧,下面用观察者模式实现上面功能以做对比,首先定义两个接口,IObserverIObservable,如下

public interface IObserver

    {

        void Notify(DrawEventArgs e);

    }

    public interface IObservable

    {

        void Register(IObserver observer);

        void UnRegister(IObserver observer);

    }

下面是改写后的两个观察者类,

    public class NewRectangle:IObserver

    {

        private ObserverManager m;

        public NewRectangle(ObserverManager oManager)

        {

            m=oManager;

            oManager.Register(this);

        }

        public void Notify(DrawEventArgs e)

        {

            Console.WriteLine(string.Format("The Rectangle'length={0} and width={1}.", e.Size * 2, e.Size));

        }

        public void Detach()

        {

            m.UnRegister(this);

        }

    }

    public class NewSquare:IObserver

    {

        private ObserverManager m;

        public NewSquare(ObserverManager oManager)

        {

            m=oManager;

            oManager.Register(this);

        }

        public void Notify(DrawEventArgs e)

        {

            Console.WriteLine(string.Format("The Square'Length = {0}.", e.Size));

        }

        public void Detach()

        {

            m.UnRegister(this);

        }

    }

下面是负责通知观察者的类型,

    public class ObserverManager:IObservable

    {

        protected ArrayList arrList;

        public ObserverManager()

        {

            arrList = new ArrayList();

        }

        public void Register(IObserver observer)

        {

            arrList.Add(observer);

        }

        public void UnRegister(IObserver observer)

        {

            if (arrList.Contains(observer))

            {

                arrList.Remove(observer);

            }

        }

        public void NotifyObservers(double size)

        {

            DrawEventArgs e = new DrawEventArgs(size);

            foreach (IObserver observer in arrList)

            {

                observer.Notify(e);

            }

        }

        public void SizeChanged(double size)

        {

            NotifyObservers(size);

        }

    }

下面是调用代码,

        static void Main(string[] args)

        {

            ObserverManager oManager = new ObserverManager();

            NewRectangle rect = new NewRectangle(oManager);

            NewSquare square = new NewSquare(oManager);

            oManager.SizeChanged(5);

            square.Detach();

            oManager.SizeChanged(10);

            Console.ReadLine();

        }

最好运行下代码,这样可以更easy的理解这两种模式微妙的差别了。

对事件来说,还可以显式的用addremove编写事件访问器,事件访问器通常有编译器生成,所以可以显式的用事件访问器修改DrawManager类型,

    public class DrawManager

    {

        private event ShapeSizeChanged m_SizeChanged;

        private readonly object m_lock = new object();

        public event ShapeSizeChanged SizeChanged

        {

            add

            {

                lock (m_lock)

                {

                    m_SizeChanged += value;

                }

            }

            remove

            {

                lock (m_lock)

                {

                    m_SizeChanged -= value;

                }

            }

        }

        protected void OnSizeChanged(DrawEventArgs e)

        {

            ShapeSizeChanged temp = m_SizeChanged;

            //是否有委托与该事件关联

            if (temp != null)

            {

                temp(this, e);

            }

        }

        public void SizeChange(double size)

        {

            DrawEventArgs e = new DrawEventArgs(size);

            OnSizeChanged(e);

        }

    }

posted @ 2011-09-13 08:34  秋无语  阅读(347)  评论(0编辑  收藏  举报