Delphi.NET 内部实现分析(3.3)
2.3. 对象
接下来我们看看类的实例,对象的实现 //-----------------------------------------Borland.Delphi.System.pas-- type TObject = System.Object;
TObjectHelper = class helper for TObject procedure Free; function ClassType: TClass; class function ClassName: string; class function ClassNameIs(const Name: string): Boolean; class function ClassParent: TClass; class function ClassInfo: TObject; class function InheritsFrom(AClass: TClass): Boolean; class function MethodAddress(const Name: string): TObject; class function SystemType: System.Type; function FieldAddress(const Name: string): TObject; procedure Dispatch(var Message); end; //-----------------------------------------Borland.Delphi.System.pas-- 从Borland.Delphi.System的定义中我们可以看到,TObject实际上就是System.Object的 别名而已,而真正的代码是通过class helper给TObject也就是System.Object打的补丁。 下面我们来仔细看看TObjectHelper的实现代码,理解Delphi是如何移植到CLR上的。 //-----------------------------------------Borland.Delphi.System.pas-- procedure TObjectHelper.Free; begin if (Self <> nil) and (Self is IDisposable) then (Self as IDisposable).Dispose; end; //-----------------------------------------Borland.Delphi.System.pas-- 与传统Delphi的用户自行管理内存模式不同,Delphi.NET使用CLR提供的自动内存管理机制, 有GC垃圾回收机制自动回收无用的内存。 但为了给用户一个自行控制外部资源(如文件句柄,网络连接)等稀缺资源的机会,CLR同时提供了 IDisposable接口这种妥协机制。一个类如果实现了IDisposable接口,则说明其有需要自己管理 生命周期的资源,可以通过IDisposable.Dispose方法手工释放。接口定义如下 IDisposable = interface procedure Dispose; end; 因而Delphi.NET的Free方法只是简单检测当前对象是否支持IDisposable接口,如支持则 直接调用IDisposable.Dispose释放资源。不过目前预览版对此接口的支持好像不是很好用 :( 如果以后能够支持象C#中using语句那样的功能就好了,呵呵 在TObjectHelper的实现中可以看到,对类方法如class function方法来说, Self就是指向类的元类,因而ClassParent和ClassInfo方法直接从其元类获取信息。 //-----------------------------------------Borland.Delphi.System.pas-- class function TObjectHelper.ClassParent: TClass; begin Result := _TClass(Self).ClassParent; end;
class function TObjectHelper.ClassInfo: TObject; begin Result := _TClass(Self).FInstanceType; end; //-----------------------------------------Borland.Delphi.System.pas-- 而对于普通的方法,则需要将其转换为Token或Type再进行处理。ClassType和FieldAddress 就是两个很好的例子。前者使用刚刚提到的_GetMetaFromHandle函数从当前对象的类型Token 获取元类;后者则从当前对象的类型Type(CLR中类似元类的概念)获取指定名称字段的对象 //-----------------------------------------Borland.Delphi.System.pas-- function TObjectHelper.ClassType: TClass; begin Result := _GetMetaFromHandle(System.Type.GetTypeHandle(Self)); end;
function TObjectHelper.FieldAddress(const Name: string): TObject; begin Result := TypeOf(Self).GetField(Name); end; //-----------------------------------------Borland.Delphi.System.pas-- 剩余方法的实现原理大同小异,无非是在对象、类、元类、Token和Type之间互相转换,获取所需的信息。 //-----------------------------------------Borland.Delphi.System.pas-- class function TObjectHelper.SystemType: System.Type; begin Result := System.Type.GetTypeFromHandle(_TClass(Self).FInstanceType); end;
class function TObjectHelper.ClassName: string; begin Result := System.Type.GetTypeFromHandle(_TClass(Self).FInstanceType).Name; end;
class function TObjectHelper.ClassNameIs(const Name: string): Boolean; begin Result := ClassName = Name; end;
class function TObjectHelper.InheritsFrom(AClass: TClass): Boolean; begin Result := TypeOf(Self).IsInstanceOfType(TypeOf(AClass)); end;
class function TObjectHelper.MethodAddress(const Name: string): TObject; begin Result := TypeOf(Self).GetMethod(Name); end; //-----------------------------------------Borland.Delphi.System.pas-- 余下一个TObjectHelper.Dispatch方法,后面分析Delphi.NET消息模型时再详谈。
|