.NET 事件
成都创新互联主要从事成都网站建设、网站制作、网页设计、企业做网站、公司建网站等业务。立足成都服务平泉,10多年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:028-86922220
事件概述
在发生其他类或对象关注的事情时,类或对象可通过事件通知它们。发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。
事件的订阅和取消
如果您想编写引发事件时调用的自定义代码,则可以订阅由其他类发布的事件。例如,可以订阅某个按钮的“单击”事件,以使应用程序在用户单击该按钮时执行一些有用的操作。
定义一个事件处理程序方法,其签名与该事件的委托签名匹配。例如,如果事件基于 EventHandler 委托类型,则下面的代码表示方法存根
- oid HandleCustomEvent(object sender, CustomEventArgs a){ }
使用加法赋值运算符 (+=) 来为事件附加事件处理程序。在下面的示例中,假设名为 publisher 的对象拥有一个名为 RaiseCustomEvent 的事件。请注意,订户类需要引用发行者类才能订阅其事件。
- publisher.RaiseCustomEvent += HandleCustomEvent;
- publisher.RaiseCustomEvent += new CustomEventHandler(HandleCustomEvent);
- publisher.RaiseCustomEvent += delegate(object o, CustomEventArgs e)
- {
- string s = o.ToString() + " " + e.ToString();
- Console.WriteLine(s);
- };
要防止在引发事件时调用事件处理程序,您只需取消订阅该事件。要防止资源泄露,请在释放订户对象之前取消订阅事件,这一点很重要。在取消订阅事件之前,在发布对象中作为该事件的基础的多路广播委托会引用封装了订户的事件处理程序的委托。只要发布对象包含该引用,就不会对订户对象执行垃圾回收。
使用减法赋值运算符 (-=) 取消订阅事件。所有订户都取消订阅某事件后,发行者类中的事件实例会设置为 null。
- publisher.RaiseCustomEvent -= HandleCustomEvent;
发布标准事件
下面的过程演示了如何将符合标准 .NET Framework 模式的事件添加到您自己的类和结构中。.NET Framework 类库中的所有事件均基于 EventHandler 委托,定义如下。
- public delegate void EventHandler(object sender, EventArgs e);
- public class CustomEventArgs : EventArgs
- {
- public CustomEventArgs(string s)
- {
- msg = s;
- }
- private string msg;
- public string Message
- {
- get { return msg; }
- }
- }
- public delegate void CustomEventHandler(object sender, CustomEventArgs a);
- public event EventHandler RaiseCustomEvent;
- class Publisher
- {
- public event CustomEventHandler RaiseCustomEvent;
- }
- public event EventHandler
RaiseCustomEvent;
#p#
引发派生类中的基类事件
以下简单示例演示了在基类中声明可从派生类引发的事件的标准方法。此模式广泛应用于 .NET Framework 基类库中的 Windows 窗体类。
在创建可用作其他类的基类的类时,必须考虑如下事实:事件是特殊类型的委托,只可以从声明它们的类中调用。派生类无法直接调用基类中声明的事件。尽管有时您可能希望某个事件只能通过基类引发,但在大多数情形下,您应该允许派生类调用基类事件。为此,您可以在包含该事件的基类中创建一个受保护的调用方法。通过调用或重写此调用方法,派生类便可以间接调用该事件。
- namespace BaseClassEvents
- {
- using System;
- using System.Collections.Generic;
- public class ShapeEventArgs : EventArgs
- {
- private double newArea;
- public ShapeEventArgs(double d)
- {
- newArea = d;
- }
- public double NewArea
- {
- get { return newArea; }
- }
- }
- public abstract class Shape
- {
- protected double area;
- public double Area
- {
- get { return area; }
- set { area = value; }
- }
- public event EventHandler
ShapeChanged; - public abstract void Draw();
- protected virtual void OnShapeChanged(ShapeEventArgs e)
- {
- EventHandler
handler = ShapeChanged; - if (handler != null)
- {
- handler(this, e);
- }
- }
- }
- public class Circle : Shape
- {
- private double radius;
- public Circle(double d)
- {
- radius = d;
- area = 3.14 * radius;
- }
- public void Update(double d)
- {
- radius = d;
- area = 3.14 * radius;
- OnShapeChanged(new ShapeEventArgs(area));
- }
- protected override void OnShapeChanged(ShapeEventArgs e)
- {
- base.OnShapeChanged(e);
- }
- public override void Draw()
- {
- Console.WriteLine("Drawing a circle");
- }
- }
- public class Rectangle : Shape
- {
- private double length;
- private double width;
- public Rectangle(double length, double width)
- {
- this.length = length;
- this.width = width;
- area = length * width;
- }
- public void Update(double length, double width)
- {
- this.length = length;
- this.width = width;
- area = length * width;
- OnShapeChanged(new ShapeEventArgs(area));
- }
- protected override void OnShapeChanged(ShapeEventArgs e)
- {
- base.OnShapeChanged(e);
- }
- public override void Draw()
- {
- Console.WriteLine("Drawing a rectangle");
- }
- }
- public class ShapeContainer
- {
- List
_list; - public ShapeContainer()
- {
- _list = new List
(); - }
- public void AddShape(Shape s)
- {
- _list.Add(s);
- s.ShapeChanged += HandleShapeChanged;
- }
- private void HandleShapeChanged(object sender, ShapeEventArgs e)
- {
- Shape s = (Shape)sender;
- Console.WriteLine("Received event. Shape area is now {0}", e.NewArea);
- s.Draw();
- }
- }
- class Test
- {
- static void Main(string[] args)
- {
- Circle c1 = new Circle(54);
- Rectangle r1 = new Rectangle(12, 9);
- ShapeContainer sc = new ShapeContainer();
- sc.AddShape(c1);
- sc.AddShape(r1);
- c1.Update(57);
- r1.Update(7, 7);
- Console.WriteLine();
- Console.WriteLine("Press Enter to exit");
- Console.ReadLine();
- }
- }
- }
#p#
实现接口事件
接口可声明事件。下面的示例演示如何在类中实现接口事件。接口事件的实现规则与任何接口方法或属性的实现规则基本相同。
在类中声明事件,然后在适当的位置调用该事件。
- public interface IDrawingObject
- {
- event EventHandler ShapeChanged;
- }
- public class MyEventArgs : EventArgs {…}
- public class Shape : IDrawingObject
- {
- event EventHandler ShapeChanged;
- void ChangeShape()
- {
- // Do something before the event…
- OnShapeChanged(new MyEventsArgs(…));
- // or do something after the event.
- }
- protected virtual void OnShapeChanged(MyEventArgs e)
- {
- if(ShapeChanged != null)
- {
- ShapeChanged(this, e);
- }
- }
- }
下面的示例演示如何处理以下的不常见情况:您的类是从两个以上的接口继承的,每个接口都含有同名事件)。在这种情况下,您至少要为其中一个事件提供显式接口实现。为事件编写显式接口实现时,必须编写 add 和 remove 事件访问器。这两个事件访问器通常由编译器提供,但在这种情况下编译器不能提供。
您可以提供自己的访问器,以便指定这两个事件是由您的类中的同一事件表示,还是由不同事件表示。例如,根据接口规范,如果事件应在不同时间引发,则可以将每个事件与类中的一个单独实现关联。在下面的示例中,订户将形状引用强制转换为 IShape 或 IDrawingObject,从而确定自己将会接收哪个 OnDraw 事件。
- namespace WrapTwoInterfaceEvents
- {
- using System;
- public interface IDrawingObject
- {
- event EventHandler OnDraw;
- }
- public interface IShape
- {
- event EventHandler OnDraw;
- }
- public class Shape : IDrawingObject, IShape
- {
- event EventHandler PreDrawEvent;
- event EventHandler PostDrawEvent;
- event EventHandler IDrawingObject.OnDraw
- {
- add { PreDrawEvent += value; }
- remove { PreDrawEvent -= value; }
- }
- event EventHandler IShape.OnDraw
- {
- add { PostDrawEvent += value; }
- remove { PostDrawEvent -= value; }
- }
- public void Draw()
- {
- EventHandler handler = PreDrawEvent;
- if (handler != null)
- {
- handler(this, new EventArgs());
- }
- Console.WriteLine("Drawing a shape.");
- handler = PostDrawEvent;
- if (handler != null)
- {
- handler(this, new EventArgs());
- }
- }
- }
- public class Subscriber1
- {
- public Subscriber1(Shape shape)
- {
- IDrawingObject d = (IDrawingObject)shape;
- d.OnDraw += new EventHandler(d_OnDraw);
- }
- void d_OnDraw(object sender, EventArgs e)
- {
- Console.WriteLine("Sub1 receives the IDrawingObject event.");
- }
- }
- public class Subscriber2
- {
- public Subscriber2(Shape shape)
- {
- IShape d = (IShape)shape;
- d.OnDraw += new EventHandler(d_OnDraw);
- }
- void d_OnDraw(object sender, EventArgs e)
- {
- Console.WriteLine("Sub2 receives the IShape event.");
- }
- }
- public class Program
- {
- static void Main(string[] args)
- {
- Shape shape = new Shape();
- Subscriber1 sub = new Subscriber1(shape);
- Subscriber2 sub2 = new Subscriber2(shape);
- shape.Draw();
- Console.WriteLine("Press Enter to close this window.");
- Console.ReadLine();
- }
- }
- }
使用字典存储事件实例
accessor-declarations 的一种用法是公开大量的事件但不为每个事件分配字段,而是使用字典来存储这些事件实例。这只有在具有非常多的事件、但您预计大部分事件都不会实现时才有用。
- public delegate void EventHandler1(int i);
- public delegate void EventHandler2(string s);
- public class PropertyEventsSample
- {
- private System.Collections.Generic.Dictionary
eventTable; - public PropertyEventsSample()
- {
- eventTable = new System.Collections.Generic.Dictionary
(); - eventTable.Add("Event1", null);
- eventTable.Add("Event2", null);
- }
- public event EventHandler1 Event1
- {
- add
- {
- eventTable["Event1"] = (EventHandler1)eventTable["Event1"] + value;
- }
- remove
- {
- eventTable["Event1"] = (EventHandler1)eventTable["Event1"] - value;
- }
- }
- public event EventHandler2 Event2
- {
- add
- {
- eventTable["Event2"] = (EventHandler2)eventTable["Event2"] + value;
- }
- remove
- {
- eventTable["Event2"] = (EventHandler2)eventTable["Event2"] - value;
- }
- }
- internal void RaiseEvent1(int i)
- {
- EventHandler1 handler1;
- if (null != (handler1 = (EventHandler1)eventTable["Event1"]))
- {
- handler1(i);
- }
- }
- internal void RaiseEvent2(string s)
- {
- EventHandler2 handler2;
- if (null != (handler2 = (EventHandler2)eventTable["Event2"]))
- {
- handler2(s);
- }
- }
- }
- public class TestClass
- {
- public static void Delegate1Method(int i)
- {
- System.Console.WriteLine(i);
- }
- public static void Delegate2Method(string s)
- {
- System.Console.WriteLine(s);
- }
- static void Main()
- {
- PropertyEventsSample p = new PropertyEventsSample();
- p.Event1 += new EventHandler1(TestClass.Delegate1Method);
- p.Event1 += new EventHandler1(TestClass.Delegate1Method);
- p.Event1 -= new EventHandler1(TestClass.Delegate1Method);
- p.RaiseEvent1(2);
- p.Event2 += new EventHandler2(TestClass.Delegate2Method);
- p.Event2 += new EventHandler2(TestClass.Delegate2Method);
- p.Event2 -= new EventHandler2(TestClass.Delegate2Method);
- p.RaiseEvent2("TestString");
- }
- }
事件的异步模式
有多种方式可向客户端代码公开异步功能。基于事件的异步模式为类规定了用于显示异步行为的建议方式。对于相对简单的多线程应用程序,BackgroundWorker 组件提供了一个简单的解决方案。对于更复杂的异步应用程序,请考虑实现一个符合基于事件的异步模式的类。
原文链接:http://www.cnblogs.com/liusuqi/p/3145324.html
网站题目:.Net事件
文章来源:http://www.mswzjz.cn/qtweb/news12/151662.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能