现在的位置: 首页 > 综合 > 正文

拿事件说那么一些事

2012年01月21日 ⁄ 综合 ⁄ 共 5908字 ⁄ 字号 评论关闭

.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);

        }

    }

【上篇】
【下篇】

抱歉!评论已关闭.