.NET简谈组件程序设计之(delegate与event关系)
本人最近一段时间在学习关于.NET组件编程方面的技术,在学习过程中确实有很多好的东西需要与大家分享。[王清培版权所有,转载请给出署名]
关于什么叫组件编程,其实就是利用.NET来开发基于组件模型的程序,面向组件编程而非面向对象编程,这是一个高度,没有很长时间的学习与磨练
是体会不到这个感觉的。我们现在的开发思想应该是以面向对象为主的,但是如何提升这个高度,只有慢慢的学习了。
其实面向组件编程包含了面向对象编程思想,将一组功能独立的封装起来供以后重复使用,但是在开发组件的过程中需要使用到面向对象的思想来构
造组件,这两个概念不矛盾,面向对象思想是具体实现,而面向组件思想应该说是站在一个产品或者说是一个框架的高度来宏观的形容。
这些技术哲学我们就不讨论了,学点实际的东西比较现实。我们只需要知道,面向对象编程是代码重用,而面向组件编程是实现的重用。而不管是面
向对象也好还是面向组件也好,归根到底都得用良好的代码来实现。只要我们在开始编码的时候,在脑海里注入这些需要考虑的想法后就可以了。
这篇文章我们先来扫除组件编程中经常用到的委托与事件的一些技术疑惑。在没有学习组件编程之前,我也是不能理解delegate与event的关系和两
者之间到用意何在。但是在最近的学习过程中以有了大概的了解,并且决定写出学习到的技术与大家分享。[王清培版权所有,转载请给出署名]
delegate在C#中表示委托的概念,而event表示事件的概念,但是这两者之间为什么需要结合起来使用,不用event也能很好的实现面向对象中的事件
的思想和功能,通过多播委托一样可以调用所有订阅者。
其实要说为什么需要用event来使用事件的机制,一句话就概括了,但是我这里先不说,说了就没啥意思了,请继续看。
我们先来看点代码:
1:
using System; using System.Collections.Generic; using System.Text; namespace EventDemo { /// <summary> /// 句柄移除委托 /// </summary> /// <param name="handle">提示信息</param> public delegate void MoveHandler(string handle); /// <summary> /// 句柄对象 /// </summary> public class ObjectHandler { /// <summary> /// 句柄事件 /// </summary> public MoveHandler hand; /// <summary> /// 触发句柄事件通知所有订阅者 /// </summary> public void Onhand() { hand("句柄事件"); } } }
2
using System; using System.Collections.Generic; using System.Text; namespace EventDemo { class Program { static void Main(string[] args) { ObjectHandler handermanager = new ObjectHandler(); handermanager.hand += handmethod; handermanager.Onhand(); } public static void handmethod(string eventstring) { Console.WriteLine(eventstring); Console.ReadLine(); } } }
为了演示效果,我随便起了个对象名称,没有什么特殊意义。
我定义了一个ObjectHandler对象,在内部使用MoveHandler委托实例表示事件对象,当调用Onhand方法的时候我通过委托实例来逐一的调用订阅者来达到事件的效果。但是一般不回将触发事件的方法定义成公共的,这里只是为了显示。
[王清培版权所有,转载请给出署名]
我们引入问题,事件是属于对象内部私有的,只能由对象来触发事件才符合面向对象规则,但是光使用委托无法达到目的。委托实例需要被订阅者订阅才行,那么委托实例必须是公共的,这个时候委托就不可能保证是谁触发了事件。
请看代码:
3:
using System; using System.Collections.Generic; using System.Text; namespace EventDemo { class Program { static void Main(string[] args) { ObjectHandler handermanager = new ObjectHandler(); handermanager.hand += handmethod; handermanager.Onhand(); /*我通过触发对象内部的委托,来蒙骗所有订阅者。 * 订阅者都认为是ObjectHandler发出的事件,其实是有人偷偷的模拟事件。*/ handermanager.hand("借刀杀人"); } public static void handmethod(string eventstring) { Console.WriteLine(eventstring); Console.ReadLine(); } } }
订阅者没有任何理由来承担这个意外的责任,ObjectHandler对象必须为此承担责任。
那么如何避免事件不被恶意者触发呢,那么这个是就需要event关键字了,如果用event修饰过后的委托实例,是无法在对象的外部被触发的。请看代码:
4:
using System; using System.Collections.Generic; using System.Text; namespace EventDemo { /// <summary> /// 句柄移除委托 /// </summary> /// <param name="handle">提示信息</param> public delegate void MoveHandler(string handle); /// <summary> /// 句柄对象 /// </summary> public class ObjectHandler { /// <summary> /// 句柄事件 /// </summary> public event MoveHandler hand; /// <summary> /// 触发句柄事件通知所有订阅者 /// </summary> public void Onhand() { hand("句柄事件"); } } }
这样就很好的维护了对象的封闭原则。
下一篇我们将学习委托的更深层次的应用"异步委托"