委托和事件
来源:互联网 发布:java游戏服务器端开发 编辑:程序博客网 时间:2024/06/11 21:56
点击提交按钮、在窗体内移动鼠标、按下回车键、在I/O端口接收一个字符,这些都是事件(event),它们常常触发程序中一个或多个特殊事件处理例程(event handling routine)调用。
在.NET中事件实际上是类成员,与成员属性和方法一样。FCL中几乎每个类都有事件成员。
委托
将事件与处理方法关联起来的是委托对象(delegate object)。该对象维护着事件发生时要调用的方法列表。
声明:
public delegate void Mystring (string msg);
声明委托时,C#编译器会创建一个sealed(密封)类,并以委托标识符(MyString)命名。该类定义了一个构造函数,它接收方法(可以是静态方法或实例方法)名作为其一个参数。该类还包含另外一些方法,以支持委托维护目标方法列表。这意味着,不同回调法。一个委托可以调用多个事件处理方法。
方法必须向委托注册,以便委托能调用这个方法。只有无返回值而且接受一个字符串参数的方法才能像这个委托注册。调用委托时,他会遍历其内部调用列表,并按照方法的注册顺序调用所有的注册方法。调用多个方法的过程称为组播(multicastring)。
组播委托
class DelegataClass
{
public delegate void MyString(string s);
public static void PrintLower(string s)
{
Console.WriteLine(s.ToLower());
}
public static void PrintUpper(string s)
{
Console.WriteLine(s.ToUpper());
}
public static void Main()
{
MyString MyDel;
//regester method to be called by delegate
MyDel = new MyString(PrintLower);
MyDel += new MyString(PrintUpper);
MyDel("Happy birthday");
}
}
输出:
happy birthday
HAPPY BIRTHDAY
注意,+=操作符用于向调用列表增加方法。相反地,可以使用-=来从操作符中删除方法。
前面的示例中委托同步的调用每一个方法,这说明,只要有前一个方法完成操作,才会调用后面的方法。这可能存在两个问题:某个方法可能被“挂起”,永远不返回控制,或是需要长时间来处理。它们都将阻塞整个系统的运用。为了解决这个问题.NET允许委托对方法执行异步调用。在这种情况下,被调用的方法与调用的方法将在不同的线程中运行,这样一来,调用方法能通过轮询来确定被调用方法何时结束,或者让被调用方法在完成时回调一个方法。
基于委托的事件处理
抽象的讲,.NET的事件模型基于贯彻者模式(Observer Design Pettern)。这个模式定义为“对象间存在一对多依赖关系,一个对象改变状态时,依赖此的所有对象都能得到通知并自动更新”。
- 处理内置事件
MouseEventDown和MouseEventHandler都是FCL中与定义的。只需要实现事件处理程序,并向委托注册即可。
+=操作符用于注册与事件相关的方法。
MouseEventDown +=new MouseEventHandler(onMouseDown);
该语句的基本结构是:
this.event += new delegate(envet handler method);
要实现事件的处理程序,就必须提供委托定义的签名。在描述MouseEventHandler委托声明的文档中可以找到该签名。
public delegate void MouseEventHandler(object sender,MonthChangedEventArgs e)
- 使用匿名方法和委托
.NET2.0引入了一种称为匿名方法(anmoymous method) 的语言构造,有了匿名方法,就不需要单独的事件处理方法;相反,事件处理代码封装在委托代中。
this.MouseDown += new MouseEventHandler(OnMouseDown);
替换为下面的语句,这条语句会创建一个委托,其中包含调用委托时要执行的代码。
this.MouseDown += delegate(object sender,EventArgs e)
{
lastX=e.X;
lastY=e.Y;
}
这个取代OnMouseDown的代码块不需要方法名,故称为匿名方法。其语法如下:
delegate [(parameter-list)]{anonymose-method-block}
- 关键字delegate放在调用委托时要执行的代码前面。
- 参数列表(可选)用于像代码块传递数据。参数必须与委托声明的的参数相匹配。
- 当C#编译器遇到匿名代码块时,将创建一个新,并在其中建立一个方法包含这个代码块。调用委托时会调用此方法。
public class TestDelegeteClass
{
//delegate declaretion
public delegate void MyString (string s);
public static void Main()
{
//register two anonymose methods with the delegate
MyString myDel;
myDel = delegate(string s) { Console.WriteLine(s.ToLower()); };
myDel = +delegate(string s) { Console.WriteLine(s.ToUpper()); };
//invoke delegate
myDel("My Name is Jiero");
}
}
调用委托时,它执行两个匿名方法中的代码,其结果就是将输入字符串分别全大写和全小写输出。
- 定义委托来处理事件
委托签名应当定义一个void返回类型,而且要由Object和EventArgs类型的参数。sender参数用来标识事件发布者,这样客户就可以使用一个方法来处理和识别源于多方的事件。
.NET提供了EventArgs类作为保存参数列表的泛型容器。这样做有几个好处,最重要的就是它使事件处理方法与事件发布者就诶出耦合。
要创建一个EventArgs类型用作参数,需要定义一个继承自EventArgs的新类。下面的例子中包含了一个string成员属性。这个成员属性的值在触发事件之前设置,在该事件中将把这个成员属性作为一个参数。
public class IOEventArgs : EventArgs
{
private string eventMsg;
public IOEventArgs(string msg){
this.eventMsg = msg;
}
public string Msg{
get { return eventMsg; }
}
}
- 它必须继承与EventArgs类。
- 类名应当以EventArgs结尾。
- 参数要定义为只读(readonly)字段或成员属性。
- 使用构造函数来初始化值。
如果事件不生成数据,就没有必要创建一个类来作为EventArgs参数。而只需要简单的传递。EventArgs.Empty即可。
如果委托使用了EventHandler签名,可将Eventhandler用作委托,而不用创建你自己的委托。这是应为,EventHandler是.NET FCL的一部分,无需声明。
- 定义定制事件
在编写自己的类时,常常要定义定制事件,在某些状态发生时发出通知。使用event关键字来指定委托,该委托将在事件发生时调用。
class Class1
{
public delegate void UserRequest(object sender, EventArgs e); //定义委托
public event UserRequest OnUserRequest; //定义一个委托类型的事件
public void run()
{
while (true)
{
if (Console.ReadLine() == "a")
{//事件监听
OnUserRequest(this, new EventArgs()); //产生事件
}
}
}
}
class Class2
{
static void Main(string[] args)
{
Class1 c1 = new Class1();
c1.OnUserRequest += new Class1.UserRequest(c1_OnUserRequest); //委托实例化后绑定到事件
c1.run();
}
private static void c1_OnUserRequest(object sender, EventArgs e)
{//事件处理方法
Console.WriteLine(" 你触发了事件!");
}
}
- c# 委托和委托事件
- 委托和事件
- 委托和事件
- 委托和事件
- 委托和事件
- 委托和事件
- 事件和委托
- 委托和事件
- 事件和委托学习
- 关于委托和事件
- C# 委托和事件
- 委托和事件
- 委托和事件
- 事件和委托
- 委托和事件
- 委托和事件
- 委托和事件
- 委托和事件
- 【想法】从代码中生成函数流程图?
- 怎样解决鼠标出现停顿的问题?
- Spring的DAO学习笔记
- SERVLET学习笔记
- JSP学习笔记(EL篇)
- 委托和事件
- SharePoint解决方案包(Solution Pack)
- 『
- moss:自动生成wsp文件
- APIMonitor v1.2.1.83
- MOSS: 强大的命令行管理功能----STSADM
- Ubuntu 8.04 Hardy Heron Alpha4正式发布
- 如何查找到SQL Server存储过程和函数里的关键词
- 跨服务器SQL查询解决方案