1、,第十四章委托、事件和反射,回顾,读写文本文件的读写器分别是什么?XML文件的节点可以自由扩展吗?,实现委托定义和触发事件理解程序集的概念理解反射的概念,本章目标,委托,函数指针类型安全用于将方法传递给其他函数,4,委托的概念,委托是一种引用方法的类型。 一旦为委托绑定(分配)了方法,委托将与该方法具有完全相同的行为。 可以为委托绑定(分配)一个方法或多个方法,绑定一个方法的委托成为单路广播委托,绑定多个方法的委托称为多路广播委托。,5,委托的声明,访问修饰符 delegate (参数列表);例如: public delegate void BankEmployee( ); 注意:委托可以理解
2、为一种类型,可以在定义类的任何地方定义委托,委托的使用,使用委托包括以下步骤:声明委托实例化委托使用委托,using System;using System.Collections.Generic;using System.Text;namespace MyExample3 public class A public int CalA(int a, int b) return (a + b); public class B public int CalB(int a, int b) return (a * b); ,class Test /声明委托 public delegate int De
3、l(int x, int y); static void Main(string args) del h; A objA = new A(); B objB = new B(); /实例化委托,将委托与方法关联起来 h = new Del(objA.CalA); /使用委托实现加法运算 int t = h(5, 3); Console.WriteLine(t); /调用方法实现乘法运算 int m=objB.CalB(5, 3); Console.WriteLine(m); ,函数签名与委托签名,函数签名由函数的返回值和参数组成。函数签名与参数名无关。,8,只能为委托分配的签名匹配的方法都可以
4、分配给该委托。 换句话说,与委托的签名(由返回类型和参数组成)匹配的任何方法都可以分配给该委托。,多播委托,包含多个方法的委托称为多播委托,调用多播委托时会依次调用这多个方法。多播委托返回值必须为void可以使用+=(+) 和 -=(-) 来添加/删除方法,delegate void MultipleDel( string param );static void Main() MultipleDel operations = new MultipleDel( SomeFunc ); operations += new MultipleDel( ANotherFunc ); operations
5、( someParam );,什么是委托?,Morning,Jack,你好,王小姐,接待外国客户,接待中国客户,什么是委托?,公司业务发展了,全世界各地都有客户。怎么办?,&%¥#!$,演示示例1 见面问好,示例1源码,public enum Language English, Chinese public static void GreetPeople(string name, Language language) switch (language) case Language.English: EnglishGreeting(name); break; case Language.Chin
6、ese: ChineseGreeting(name); break; ,什么是委托?,public void GreetPeople(string name, Language lang),参数类型,参数变量,假如GreetPeople()方法可以接受一个参数变量,这个变量可以代表另一个方法,当我们给这个变量赋值 EnglishGreeting的时候,它代表着 EnglsihGreeting() 这个方法;当我们给它赋值ChineseGreeting 的时候,它又代表着ChineseGreeting()方法。,什么是委托?,参数变量命名为 MakeGreeting,MakeGreeting(n
7、ame);,public void GreetPeople(string name, * MakeGreeting) MakeGreeting(name);,什么类型?,委托,MakeGreeting参数所能代表的 ChineseGreeting()和EnglishGreeting()方法的签名:,应该能够确定 MakeGreeting可以代表的方法种类,即MakeGreeting可以代表的方法 的 参数类型和返回类型。,public void EnglishGreeting(string name)public void ChineseGreeting(string name),MakeGr
8、eeting的 参数类型定义,委托参数,委托定义了MakeGreeting参数所能代表的方法的种类,也就是MakeGreeting参数的类型。,public delegate void GreetingDelegate(string name);,public void GreetPeople(string name, GreetingDelegate MakeGreeting) MakeGreeting(name);,演示示例2 Delegate,小结,委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If
9、-Else(Switch)语句,同时使得程序具有更好的可扩展性。,总结,进入的委托实例时,它调用列表中的方法,委托调用所使用的参数和返回的值均与该方法的对应项相同。调用委托与调用方法相似。唯一的区别在于不是调用委托的实现,而是调用与委托相关联的方法的实现代码。,事件,“请听题”,集中注意力聆听,其他人,事件源,事件的发布者,事件的订阅人,不关心,未订阅该事件,定义事件 为对象订阅该事件 将发生的事件通知给订阅人,定义事件,访问修饰符 event 委托名 事件名;,语法,定义事件时,发布者首先定义委托,然后根据委托定义事件。,/声明一个委托 public delegate void Del();
10、 /声明一个事件 public event Del Click;,订阅事件,订阅事件只是添加一个委托,事件引发时该委托将调用一个方法。事件可用作 += 和 -= 运算符左边的操作数。这些运算符分别用于将事件处理程序添加到所涉及的事件或从该事件中移除事件处理程序。,me.Click += new MyEvent.Del(me.ClickMethod);,if (Click != null) Console.WriteLine(引发事件:); Click(); ,通知订阅对象,调用订阅特定事件的对象的所有委托,示例,/创建一个事件类class MyEvent /声明一个委托 public dele
11、gate void Del(); /声明一个事件 public event Del Click; /创建一个触发事件的方法 public void OnClick() if (Click != null) Console.WriteLine(引发事件:); Click(); /和事件关联的方法 public void ClickMethod() Console.WriteLine(您触发了Click事件!); ,class Test static void Main(string args) MyEvent me = new MyEvent(); /给对象预定事件 me.Click += ne
12、w MyEvent.Del(me.ClickMethod); me.OnClick(); ,小结,我们有个高档的热水器,我们给它通上电,当水温超过95度的时候:1、扬声器会开始发出语音,告诉你水的温度;2、液晶屏也会改变水温的显示,来提示水已经快烧开了。,现在写个程序来模拟这个烧水的过程:首先定义一个类来代表热水器,Heater,它有代表水温的字段,叫做temperature;当然,还有必不可少的给水加热方法BoilWater(),一个发出语音警报的方法MakeAlert(),一个显示水温的方法,ShowMsg()。,演示示例4 Heater,事件,现在假设热水器由三部分组成:热水器、警报器、
13、显示器,它们来自于不同厂商并进行了组装。那么,应该是热水器仅仅负责烧水,它不能发出警报也不能显示水温;在水烧开时由警报器发出警报、显示器显示提示和水温。,警报器和显示器告诉热水器,它对它的温度比较感兴趣(注册)。 热水器知道后保留对警报器和显示器的引用。 热水器进行烧水这一动作,当水温超过95度时,通过对警报器和显示器的引用,自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方法。,演示示例5 Heater,26,事件模型,事件源,声明,事件,触发事件条件,触发,通知,(发布者),订阅者,侦听,执行,方法,通知,订阅者,侦听,执行,方法,事件的概念,事件:是类(或类的实例)
14、在发生其某些特殊的事情时用来通知其他对象的一种方式,什么是程序集,为什么只运行这个.exe文件就能使用我们程序的所有功能?,什么是程序集,.NET框架应用程序的生成块包含编译好的代码的逻辑单元创建的每个项目文件(project)都会产生一个程序集dll,程序集的结构程序集清单类型元数据IL代码资源,向其他应用程序公开,并由这些应用程序使用,元数据是二进制信息,程序中的图片、音乐文件,程序集清单,程序集清单:元数据重要部分,ILDasm,ILDasm 反编译的工具。可以查看IL汇编代码可以看到类和方法,演示: 使用ILDasm,Visual Studio创建程序集,Visual Studio的所
15、有应用程序都创建程序集,AssemblyInfo.cs,用于配置程序集的属性,AssemblyInfo.cs介绍,AssemblyInfo.cs文件,assembly: AssemblyTitle(My News Reader)assembly: AssemblyDescription()assembly: AssemblyConfiguration()assembly: AssemblyCompany(Jade Bird)assembly: AssemblyProduct(My News Reader)assembly: AssemblyCopyright(版权所有 (C) Jade Bir
16、d 2007)assembly: AssemblyTrademark()assembly: AssemblyCulture()assembly: AssemblyVersion(1.0.0.0)assembly: AssemblyFileVersion(1.0.0.0),程序集与 internal 访问修饰符,internal修饰符用于程序集级别指定访问性internal修饰的成员不能被其它程序集访问,反射,可以ILDasm反编译工具浏览一个dll和exe的构成,这种机制叫做反射(Reflection),应用程序或dll,类的属性,类的方法,应用程序信息,用于在运行时通过编程方式获得类型信息,
17、反射,现场演示,通过代码演示获取dll的版本号,using System.Reflection;,演示示例6 反射演示,class Program static void Main(string args) string version = Assembly.LoadFile(D:MyNewsReader.exe) .GetName().Version.ToString(); Console.WriteLine(version); ,引入命名空间,反射,总结,什么是委托?使用委托包括什么步骤?什么是发布者?什么是订阅者?使用事件有哪些步骤?简述AssemblyInfo.cs 中包含的主要内容?被internal修饰的方法,能被其它应用程序调用吗?,