第十二章 委托[《.net框架程序设计》读书笔记]
一、 委托的使用
静态委托和实例委托,使用方法类似,这里给出一个使用可变参数委托的例子:
using System;
public class DelCls
{
public delegate void DelDef(params string[] strParams);
public static void CallDel(DelDef dd)
{
if(dd != null) //请务必在此处进行判断,这是个好习惯
{
dd("Hello", "world");
}
}
}
public class DelIns
{
//声明为private(私有)成员并不影响在类型内部使用委托
private static void ClsCallStr(params string[] strParams) //类型方法
{
//将字符串数组并顺序输出
foreach(string str in strParams)
{
Console.Write("{0} ", str);
}
Console.WriteLine();
}
public void InsCallStr(params string[] strParams) //实例方法
{
//将字符串数组并反序输出
for(int i = strParams.Length - 1; i >= 0; i --)
{
Console.Write("{0} ", strParams[i]);
}
Console.WriteLine();
}
public static void Main()
{
DelIns di = new DelIns();
DelCls.DelDef dd = null;
Console.WriteLine("combine two delegate:");
dd += new DelCls.DelDef(DelIns.ClsCallStr);
dd += new DelCls.DelDef(di.InsCallStr);
DelCls.CallDel(dd);
Console.WriteLine("remove the first delegate:");
dd -= new DelCls.DelDef(DelIns.ClsCallStr);
DelCls.CallDel(dd);
}
}
/*运行结果
combine two delegate:
Hello world
world Hello
remove the first delegate:
world Hello
*/
在C#中使用委托方法:
l 创建委托所使用的方法必须和委托声明相一致(参数列表、返回值都一致)
l 利用 +=、-=来进行委托的链接或取消链接或直接使用Delegate.Combine和Delegate.Remove方法来实现
l 使用MulticastDelegate的实例方法GetInvocationList()来获取委托链中所有的委托
二、 委托揭秘
所有的委托都继承自MulticastDelegate,编译器在编译时刻为委托的声明生成了一个完整的委托类,重点注意其中的一些成员:
ü 构造函数,传入委托的目标对象(实例)及指向回调方法的整数
ü 继承自MulticastDelegate的_target(System.Object)字段
ü 继承自MulticastDelegate的_methodPtr(System.Int32)字段
ü 继承自MulticastDelegate的_prev(System.MulticastDelegaet)字段
ü 生成的与方法声明相一致Invoke函数用以调用方法
可利用MulticastDelegate中的Method及Target属性来考察_methodPtr及_target字段的性质。
关于编译器生成的委托类及Invoke方法的调用情况,可通过使用ILDAsm.exe查看执行文件的IL代码获得
将上例中类型DelIns中的Main方法作如下修改,以实验GetInvocationList及MulticastDelegate中属性的使用:
public class DelIns
{
…
public static void Main()
{
…
Delegate[] arrDel = dd.GetInvocationList();
foreach(DelCls.DelDef d in arrDel)
{
Console.WriteLine("Object type: {0}, Method name: {1}",
(d.Target != null) ? d.Target.GetType().ToString() : "null",
d.Method.Name);
}
…
}
…
}
/*运行结果
…
Object type: null, Method name: ClsCallStr
Object type: DelIns, Method name: InsCallStr
…
*/
三、 委托判等
首先判断_methodPtr及_target字段是否相等,若不等则返回false;
若相等,继续判断_prev是否为null(指向委托链头部的委托),若为null,则相等返回true;
若不等,继而判断委托链上所有委托对象,重复上述步骤。
可见牵涉到委托链的时候是个递归判断的过程。
四、 委托链
l 首先被加入到委托链中的委托位于委托链的尾部,但首先被调用,这是因为Invoke中利用递归对委托函数进行调用,这样位于头部的委托最后被调用。
l 委托调用后的返回值,只是最后一次被调用方法的返回值,即委托链头部委托的返回值
l 每调用一次Remove方法只删除匹配的第一个委托链
五、 委托与反射
以下是.net framework sdk文档提供的Delegate.CreateDelegate方法列表:
创建指定类型的委托以表示指定的静态方法。
[C#] public static Delegate CreateDelegate(Type, MethodInfo);
创建指定类型的委托,该委托表示要对指定的类实例调用的指定实例方法。
[C#] public static Delegate CreateDelegate(Type, object, string);
创建指定类型的委托,该委托表示指定类的指定静态方法。
[C#] public static Delegate CreateDelegate(Type, Type, string);
创建指定类型的委托,该委托表示要按指定的大小写敏感度对指定类实例调用的指定实例方法。
[C#] public static Delegate CreateDelegate(Type, object, string, bool);
下面的示例演示了创建静态方法委托、实例方法委托以及动态调用委托:
using System;
using System.Reflection;
public class DelReflection
{
public delegate void GoGo(string strPam, Int32 nPam);
public static void ClsGo(string strPam, Int32 nPam)
{
Console.WriteLine("In class, String:{0}, Int32:{1}", strPam, nPam);
}
public void InsGo(string strPam, Int32 nPam)
{
Console.WriteLine("In instance, String:{0}, Int32:{1}", strPam, nPam);
}
public static void Main()
{
Delegate d = null;
d = Delegate.CreateDelegate(typeof(GoGo), typeof(DelReflection), "ClsGo");
if(d != null)
d.DynamicInvoke(new Object[]{"Hello", 45});
DelReflection dr = new DelReflection();
d = Delegate.CreateDelegate(typeof(GoGo), dr, "InsGo");
if(d != null)
d.DynamicInvoke(new Object[]{"Hello", 45});
}
}
/*运行结果
In class, String:Hello, Int32:45
In instance, String:Hello, Int32:45
*/
下一篇:第十一章 事件[《.net框架程序设计》读书笔记] >>
相关文章:
- · .NET框架程序设计读书笔记(三)--.net框架类库(FCL)和通用类型系统、代码互操作
- · NET框架程序设计读书笔记(三)--执行程序集代码
- · 动态加载树----treeView
- · 在Internet上用通过.Net Remoting机制实现服务器对客户端的直接调用
- · .NET中的强名称机制
- · .NET中的GAC
- · .net框架程序设计读书笔记二(Microsoft .net 框架开发平台体系架构)
- · .net 框架程序设计 读书笔记(一)---.net 平台构成
- · .NET中的版本号
- · Win32类型和.net类型的对应表
- · 实战 .Net 数据访问层 - 1
- · 基于.Net的AOP实现技术
- · 非常了不起的工具iNET----------帮你实现.NET项目跨平台运行.
- · 服务器端异步 Web 方法
- · Prototype设计模式的实现
- · 用WinDbg探索CLR世界 [3] 跟踪方法的 JIT 过程
- · .net+oracle+crystalReports开发web应用程序学习笔记(二)
- · 使用.net Remtoing进行并行计算
- · 我的O/R Mapping实际开发经验之谈(二)
- · 走近COM Interop——RCW入门
- · 基于Grove的.NET应用程序开发提示
- · datagrid的正反双向排序
- · DataGrid在分页状态下删除纪录的问题
- · 未找到路径“D:\”的一部分 的问题解决
- · 在下拉列表框中显示多列的两种简易实现方式
- · .NET 1.1中预编译ASP.NET页面实现原理浅析 [1] 自动预编译机制浅析
- · IEWebControl TreeView右键菜单实例
- · 正则表达式测试程序
- · 创建插件框架(2)
- · 创建插件框架(1)
- · 来自开源社区的声音: .NET vs JAVA
- · .net下分层架构系统的开发技术规范(2)
- · 在.NET 中模拟提交Post数据
- · 以武學的視角來戲說.NET程序員的倚天之術
- · XP方法学习总结及对小组开发的思考
- · 程序员的.NET时代(二)
- · 程序员的.NET时代(一)
- · 品味.NET巨著——书评《Microsoft .NET框架程序设计(修订版)》
