第三章 组件编程概述
组件是软件应用的构造块。组件封装了状态和执行逻辑,并能在不同的应用程序中被复用,组件使得应用程序模块化,这更有利于应用程序的开发和维护。
.NET组件的重要特性:属性(property)、方法(method)、事件(event)、元数据(metadata)atrribute
.NET组件的重要特性:属性(property)、方法(method)、事件(event)、元数据(metadata)atrribute
- 托管组件概述
CLR给托管组件提供了低层渠道,这样可以把注意力完全放在组件功能的设计和实现上,CLR实现了语言的互操作、自动内存管理、代码访问安全等,托管组件还有简单的部署模型并且升级更加容易。
设计和实现组件时需要遵循的一些指南的摘要:
1)应该使用针对CLR的编程语言来创建组件,如C#、VB.NET等
2)用属性、方法和事件来描述对象模型,用元数据attribute描述组件成员
3)确保成员与公共语言规范(CLS)一直,以能被基于CLR大其他语言所用
4)确保组件是遵照.NET框架设计指南实现的,这些指南中包括命名约定和实现方式
5)为了获得.NET框架的设计器架构中的全部优势,应实现IComponent接口或通过实现这个接口的类(如System.ComponentModel.Component)来派生
6)在一个配件中部署托管组件作为类库的一部分 - 属性
属性封装了组件的状态,是快速应用开发(RAD)的基本要素;
属性结构允许抽象来自组件客户端的属性的实现和存储;
属性可以同时定义获取操作和设置操作或只定义其中一个,不鼓励定义只写属性,如果有需要,应该实现一个方法取代属性来提供相同的功能;
属性可以具有运行期所允许的任何访问级别,包括公用的、私有的、保护的或内部的;
尽管获取操作和设置操作不像方法一样可以直接访问,但它们在语义上和方法等价;
属性还能实现任何程序逻辑、被重载或抛出异常。
1)虚拟属性:
重载虚拟属性:如果两种属性访问操作都在基类中定义,就必须在重载属性时重载这两种访问操作,如果只想重载一个访问操作,可以让另一个访问操作来委托这个基类,如下代码:
虚拟属性不能在派生类中被密封(具有不可重载性),虚拟属性还和版本有关系,一旦定义了虚拟属性,就必须在其以后的组件版本中用virtual标记这个属性,否则,将破坏现有的派生类。1 public voerride int Number
2 {
3 //被重载
4 get
5 {
6 if (_number > 0)
7 {
8 return _number;
9 }
10 return base.Number;
11 }
12 //未被重载
13 set
14 {
15 base.Number = value;
16 }
17 }
2)一个设计良好的组件在其属性设置操作中应该具有查错功能。
3)属性的命名准则:用名词或名词短语作为属性名;用Pascal规范书写,即把每个属性名的第一个字母大写并把后读的每个单词的首字母大写。
4)属性的优点:数据隐藏、验证、重载、版本化、设计器支持、数据绑定 - 方法
方法描述动作,属性描述数据。如果需要只写属性,则用方法的实现来代替。
1)方法和方法参数的命名准则:用表示任务完成的动词或动词短语给方法命名,用Pascal命名规范;用描述型参数名,用camel规范给参数命名,即参数名的第一个字母小写,接下来的单词的第一个字母大写,命名要根据参数的意义,而不是根据参数的类型。 - 事件
事件是当有动作发生或状态改变时,类发出的信息或通知。状态的发生或改变应该由用户界面动作初始化。
基于事件的编程需要一种中间机制来联系源和订阅者,在设计实现中,事件架构需要一些回调机制,.NET通过委托(delegete)来提供回调功能。
委托是一个可以对方法进行引用的类。与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用。这样,委托就等效于一个类型安全函数指针或一个回调。
1)委托:委托将函数作为参数传递。委托的类型安全要求作为委托传递的函数拥有同委托声明相同的签名。不能撰写包含 out 参数的委托。委托是事件的基础。
以下是声明及使用委托的一个简单示例:
System.MulticastDelegate在.NET框架中是委托的基类,派生于System.Delegate类,委托的类型不是直接派生于Delegate,而是十派生于MulticastDelegate,它继承了Delegate的功能以给方法绑定一个委托。MulticastDelegate还包含一个委托的链表-invocation list,通过它可以添加和删除委托。1 // keyword_delegate.cs
2 // delegate declaration
3 delegate void MyDelegate(int i);
4
5 class Program
6 {
7 public static void Main()
8 {
9 TakesADelegate(new MyDelegate(DelegateFunction));
10 }
11
12 public static void TakesADelegate(MyDelegate SomeFunction)
13 {
14 SomeFunction(21);
15 }
16
17 public static void DelegateFunction(int i)
18 {
19 System.Console.WriteLine("Called by delegate with number: {0}.", i);
20 }
21 }
22
23
24 输出:
25 Called by delegate with number: 21.
26
不能自己通过派生MulticastDelegate来定义委托,只有语言编译器和运行期能生成派生于MulticastDelegate地类型。
绑定方法方法如果是静态方法且不在同一个类中,必须用类名代替实例名。
2)事件委托:能产生事件(发送通知)的类都有一个委托成员。想接收事件的类都提供了一个可以执行一定的逻辑来响应事件的方法(事件处理程序方法)。
接收器或其他的类会给委托绑定事件处理程序并把委托添加到事件源的invocation列表中。为了产生事件,事件源调用它的委托,将在invocation列表中依次调用委托。那些委托一次调用所绑定的处理程序,完成事件序列。
上面是一个.NET框架中常见到可访问事件委托System.EventHandler,在.NET框架中事件委托的签名与EventHandler委托是相似的。1 public delegate void EventHandler(object sender, EventArgs e);
特定的签名约定:事件委托的返回类型是void;一个事件委托带有两个参数,第一个是object类型,表示事件的发送者,第二个参数描述事件的数据,是由System.EventArgs派生出来的类的实例。
将事件处理程序和事件相关联的过程(添加委托给invocation列表)叫做事件布线(event wiring),从事件中删除事件处理程序的过程(从invocation列表中删除委托)叫做事件撤线(event unwiring)。
C#中的布线撤线语法如下:
3)引发事件:为了在类中实现事件,需要一个事件数据的类、事件委托、在类中拥有invocation列表的委托成员,以及一个发布事件通知的方法。1 this.Button1.Click += new System.EventHandler(this.myEventHandler);
2 this.Button1.Click -= new System.EventHandler(this.myEventHandler);
步骤:
1.如果类没有任何关联的事件数据,对事件数据使用EventArgs类,或者使用其他实现已存在的事件数据类(如果能匹配事件的话),如果不存在一个合适的事件数据类,则定义一个事件来包含事件数据,这个类必须从System.EventArgs中派生;
2.如果事件没有关联数据,使用第一步的EventArgs,用System.EventHandler作为事件委托,或使用能匹配事件的预先存在地其他委托,如果不存在一个合适的事件委托,则定义一个事件委托,该委托的第二个参数具备来自第一步的事件数据类的类型;1 public class LowChargeEventArgs : EventArgs {
}
3.在类里,用event关键字定义事件成员,将事件名传递给事件成员,成员的类型是第二步中的事件委托类型;1 public delegate void LowChargeEventHandler(object sender, LowChargeEventArgs e);
4.在类里,定义一个虚拟(可重载)方法调用事件委托——在检查是否有事件监听器存在之后,方法的名字是在事件名前加前缀On,On<EventName>方法的目的是允许派生于你的类的类可以处理没有关联事件处理程序的事件;1 public event LowChargeEventHandler LowCharge;
1 protected virtual void OnLowCharge(LowChargeEventArgs e) {
2 if (LowCharge != null) {
3 LowCharge(this, e);
4 }
5 } - 元数据attribute
C#中attribute的语法
运行期attribute是ASP.NET完成请求/应答周期功能所必需的;1 [Browsable(false)]
2 public int Number{
}
设计期attribute是在可视化设计工具中提高了设计期的外观和控件的行为。
类级别的attribute:DesignerAttribute
属性和级别和事件级别的attribute1 [
2 Designer(typeof(MSPress.ServerControls.Design.MyLabelDesigner)),
3 Editor(typeof(MSPress.ServerControls.Design.MyLabelComponentEditor), typeof(ComponentEditor))
4 ]
5 public class MyLabel : Label {
}
1 [
2 Bindable(true),
3 DefaultValue("100"),
4 Description("The AnnounceHits event is raised when Hits is divisible by Multiple.")
5 ]
6 public int Multiple {
}
7
8 [
9 Category("Default"),
10 Description("Raised when Hits is divisible by Multiple")
11 ]
12 public event EventHandler AnnounceHits {
} - 可设计的组件和控件
在.NET框架中,可设计的组件和控件是一个类,它可以直接或间接地派生自System.ComponentModel.Component或实现System.ComponentModel.IComponent接口。
posted on 2005-12-30 16:39 ............. 阅读(205) 评论(0) 收藏 举报
浙公网安备 33010602011771号