Delphi.NET 内部实现分析(3.4)
由此我们可以看出,Delphi.NET中使用了从内嵌子类到class helper种种方法, 才总算解决了从传统继承模型和内存模型迁移到CLR以及FCL类树的过程,迁移过程不可谓不艰辛。 虽然这种解决方法不能算是完美,但相信Borland也是在综合评估了诸多其它手段之后, 才做出这样的选择,付出了一些代价、如class helper,也取得了不少的成果、源代码级兼容较强。 这种映射模型到底行不行,我想只能有待时间来做评论。 最后我们来看看Delphi的is和as关键字是如何在Delphi.NET中实现的 //-----------------------------------------Borland.Delphi.System.pas-- function _IsClass(Obj:TObject; Cls:TClass): Boolean; var t1, t2: System.Type; begin if not Assigned(Obj) then Result := false else begin t1 := Obj.GetType; t2 := System.Type.GetTypeFromHandle(_TClass(Cls).FInstanceType); if t1 = t2 then Result := true else Result := t1.IsSubclassOf(t2); end; end; //-----------------------------------------Borland.Delphi.System.pas-- _IsClass函数实现很简单,检测对象有效性后直接通过判断两个类型的继承关系检测。 //-----------------------------------------System.pas-- function _IsClass(Child: TObject; Parent: TClass): Boolean; begin Result := (Child <> nil) and Child.InheritsFrom(Parent); end; //-----------------------------------------System.pas-- 相比之下Delphi的is实现更简单,直接用TObject.InheritsFrom实现。 Delphi.NET之所以不象Delphi那样直接使用TObject.InheritsFrom实现is关键字, 是因为相对于Type.IsSubclassOf方法来说,TObjectHelper.InheritsFrom方法 使用的Type.IsInstanceOfType方法代价较大。 Type.IsSubclassOf方法只是从传入类型开始,一级一级查看其父类是否自己。 //-----------------------------------------Type.cs-- public abstract class Type : MemberInfo, IReflect { public virtual bool IsSubclassOf(Type c) { Type p = this; if (p == c) return false; while (p != null) { if (p == c) return true; p = p.BaseType; } return false; } } //-----------------------------------------Type.cs-- 而Type.IsInstanceOfType则要考虑Remoting、COM、接口以及运行时类型等等 诸多复杂因素,因而不适合用在is/as这样频繁使用的关键字实现上。 //-----------------------------------------Borland.Delphi.System.pas-- function _AsClass(Obj:TObject; Cls:TClass): TObject; begin Result := Obj; if not _IsClass(Obj, Cls) then raise System.FormatException.Create('Invalid Cast'); end; //-----------------------------------------Borland.Delphi.System.pas-- as操作符的实现,只是简单的赋值加检测而已,因为CLR是单根结构,所以转换总是成功的, 只需在转换后用is操作符检测,抛出异常情况就行。 //-----------------------------------------System.pas-- function _AsClass(Child: TObject; Parent: TClass): TObject; {$IFDEF PUREPASCAL} begin Result := Child; if not (Child is Parent) then Error(reInvalidCast); // loses return address end; //-----------------------------------------System.pas-- 可以看到Delphi中的实现也是非常类似的。
最后一个相关函数是_ClassCreate,用于实现类型的创建与构造。 //-----------------------------------------Borland.Delphi.System.pas-- function _ClassCreate(Cls: TClass; Params: Array of TObject): TObject; begin Result := System.Activator.CreateInstance(Cls.SystemType, Params); end; //-----------------------------------------Borland.Delphi.System.pas-- 与Delphi的System.pas中冗长的_ClassCreate函数实现相比,Delphi.NET无需关心 类的内存获取、构造异常的截获以及Self指针的修正等等,只是简洁的通过System.Activator类 完成所需功能,这就是底层有一个强大完善类库支持的优势所在。 至此,Borland.Delphi.System单元中关于元类、类与对象的相关定义及实现就基本上分析完了, 虽然只有寥寥百来行代码,但它为Delphi在CLR上的映射打下了坚实的基础。 下一节我们将进一步看看Delphi中消息与方法的映射关系是如何在Delphi.NET中模拟的。 
|