介绍.NET中的委派(Delegates)之三

来源:网络收集 责任编辑:栏目编辑 发表时间:2013-07-01 17:17 点击:
 因为所有的委派都派生于MulticastDelegate,它们继承了MulticastDelegate的域,属性和方法。在所有这些成员中,你要特别注意三个私有(private)域:

用于委派类型的私有域:

类型 描述
_target System.Object 指回调函数被调用时应该操作的对象。用于实例方法回调
_methodPtr System.Int32 内部整型,CLR用它来标示被回调的方法
_prev System.MulticastDelegate 指另一个委派对象,通常为null



  所有的委派都有代两个参数的构造器:一个参数是对象引用,一个是指代回调方法的整型。但是,如果你检查源代码,就会发现明白诸如App.FeedbackToConsole 或 appobj.FeedbackToFile的传递使用值进行的。你的敏感会告诉你这个代码不能编译!

  然而,编译器知道某个委派被创建,同时编译器解析源代码以决定引用哪个对象和方法。对象引用被传递为目标参数,并且用某个特定的Int32值(从某个MethodDef或MethodRef元数据符号获得)标示的方法被传递为methodPtr参数。对于静态方法,null被传递为目标参数。在构造器内部,这两个参数被存储在它们对应的私有(private)域中。

  另外,构造器将这个域置为null。这个域被用来创建一个MulticastDelegate对象链表。现在我们暂时忽略_prev域,在后续文章中将会详细讨论有关它的内容。

每一个委派对象实际上就是一个方法包装器,当方法被调用时,受作用的对象被操作。MulticastDelegate类定义两个只读公共实例属性:Target和Method。给定一个委派对象引用,你就可以查询到它的这些属性。如果方法被回调,Target属性返回一个对将要操作的对象的引用。如果方法是静态的,则Target返回null。Method属性返回标示回调方法的System.Reflection.MethodInfo对象。

  你可以用几种方式使用这些信息。一种方式是检查是否某个委派对象引用特定类型的实例方法:

//

Boolean DelegateRefersToInstanceMethodOfType(

MulticastDelegate d, Type type) {


return((d.Target != null) && d.Target.GetType == type);

}

//


你还应该编写代码检查是否回调方法由专门的名字(如FeedbackToMsgBox):

//

Boolean DelegateRefersToMethodOfName(

MulticastDelegate d, String methodName) {


return(d.Method.Name == methodName);

}

//

现在你知道了如何构造委派对象,下面让我们来谈谈回调方法是如何被调用的。为方便起见,我们还是使用

Set类中的ProcessItems:

//

public void ProcessItems(Feedback feedback) {

for (Int32 item = 1; item <= items.Length; item++) {

if (feedback != null) {

// 如果指定任何回调,则调用它们

feedback(items[item], item, items.Length);

}

}

}

//


  注释行下面的那一行代码就是调用回调方法。仔细看看代码,它调用feedback函数并传递三个参数。但是feedback是不存在的。再一次指出,编译器知道feedback是个引用某个委派对象的变量,并且编译器会产生实际的代码来调用委派对象的Invoke方法。换句话说,编译器看到下面这行代码后:

feedback(items[item], item, items.Length);

编译器产生的结果与下面这行源代码产生的结果一样:

feedback.Invoke(items[item], item, items.Length);
事实上,通过使用ILDasm.exe程序检查ProcessItems代码结果(如图五),你能发现这一点。

    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    用户名: 验证码:点击我更换图片
    最新评论 更多>>

    推荐热点

    • 浅析.NET下XML数据访问新机制
    • asp.net 面试+笔试题目第1/2页
    • C# 邮件地址是否合法的验证
    • C#高级编程:数据库连接[1]
    • asp.net 设置GridView的选中行的实现代码
    • 经典C++程序1
    • IIS 自动回收导致后台定时器失效的问题解决
    • ASP.NET&#160;GridView列表代码示例
    • 微软ASP.NET站点部署指南(3):使用Web.Config文件的Transforma
    网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
    Copyright © 2008-2015 计算机技术学习交流网. 版权所有

    豫ICP备11007008号-1