Delphi.NET 内部实现分析(3.2)
来源:百度文库 编辑:神马文学网 时间:2024/04/28 11:55:45
首先我们来看看元类的定义与实现
//-----------------------------------------Borland.Delphi.System.pas--
type
TObject = System.Object;
_TClass = class;
TClass = class of TObject;
_TClass = class
protected
FInstanceType: System.RuntimeTypeHandle;
FClassParent: _TClass;
public
constructor Create; overload;
constructor Create(ATypeHandle: System.RuntimeTypeHandle); overload;
constructor Create(AType: System.Type); overload;
function ClassParent: TClass; virtual;
end;
TClassHelperBase = class(TObject)
public
FInstance: TObject;
end;
//-----------------------------------------Borland.Delphi.System.pas--
上一节我们大概分析过元类的实现原理。每一个类有一个对应的嵌套子类,
名称为@Meta前缀加上类名,此类从Borland.Delphi.System._TClass类继承出来,
在实现上类似TClassHelperBase,只不过FInstance是类一级的静态成员变量。
.class /*0200000D*/ auto ansi nested public beforefieldinit @MetaTDemo
extends Borland.Delphi.System.@TClass/* 02000003 */
{
.field /*0400000E*/ public static class HelloUnit.TDemo/* 02000005 *//@MetaTDemo/* 0200000D */ @Instance
.method /*06000027*/ private hidebysig specialname rtspecialname static
void .cctor() cil managed
.method /*06000026*/ public hidebysig specialname rtspecialname
instance void .ctor() cil managed
.method /*06000008*/ public instance void
Hello() cil managed
}
元类的静态构造函数如上一节中的@MetaTDemo..cctor()函数,构造一个元类的实例
放入元类的@Instance静态成员
private static TDemo.@MetaTDemo..cctor() {
TDemo.@MetaTDemo.@Instance = new @MetaTDemo..ctor();
}
元类的构造函数则载入自己类型的Token到FInstanceType字段中。
public TDemo.@MetaTDemo..ctor() : base() {
this.FInstanceType = Token of TDemo;
}
这个Token在CLR中起到索引的作用,用以在Metadata诸多表中定位特定的表项,
每种元素如类、方法、字段、属性等等都有其自己的Token。在BCL中Token表现为
RuntimeTypeHandle类型,用于诸如Type.GetTypeFromHandle之类函数,
可以通过Type.TypeHandle获取。
关于Token的重要性及物理实现上用法请参加前面提到的我对Metadata分析的文章。
元类这里保存的FInstanceType实际上就是类似于Delphi中VMT指针的索引。
//-----------------------------------------Borland.Delphi.System.pas--
constructor _TClass.Create;
begin
inherited Create;
end;
constructor _TClass.Create(ATypeHandle: System.RuntimeTypeHandle);
begin
inherited Create;
FInstanceType := ATypeHandle;
end;
constructor _TClass.Create(AType: System.Type);
begin
Create(AType.TypeHandle);
end;
//-----------------------------------------Borland.Delphi.System.pas--
可以看到_TClass的几种形式构造函数,实际上都是围绕着这个Token做文章。
//-----------------------------------------Borland.Delphi.System.pas--
function _TClass.ClassParent: TClass;
begin
if not Assigned(FClassParent) then
FClassParent := _TClass.Create(System.Type.GetTypeFromHandle(FInstanceType).BaseType.TypeHandle);
Result := FClassParent;
end;
//-----------------------------------------Borland.Delphi.System.pas--
而_TClass.FClassParent则是在需要时填充的父类的元类。注意这里的转换Token到
CLR中类型的方法。System.Type.GetTypeFromHandle函数和后面要使用到的
System.Type.GetTypeHandle函数完成Type与Token之间的双向转换。
因此可以说在Delphi.NET中,元类实际上就是对类的Token的一个封装。
在了解了元类的实现后,我们来看看如何从一个Token获取其元类。
//-----------------------------------------Borland.Delphi.System.pas--
var
MetaTypeMap: Hashtable;
function _GetMetaFromHandle(ATypeHandle: System.RuntimeTypeHandle): _TClass;
var
t: System.Type;
begin
if not Assigned(MetaTypeMap) then
MetaTypeMap := Hashtable.Create;
Result := _TClass(MetaTypeMap[ATypeHandle]);
if not Assigned(Result) then
begin
t := System.Type.GetTypeFromHandle(ATypeHandle);
t := t.GetNestedType(‘@Meta‘ + t.name, BindingFlags(Integer(BindingFlags.Public) or
Integer(BindingFlags.NonPublic)));
if Assigned(t) then
begin
Result := _TClass(t.GetField(‘@Instance‘).GetValue(nil));
MetaTypeMap.Add(ATypeHandle, Result);
end
else
begin
Result := _TClass.Create(ATypeHandle);
end;
end;
end;
//-----------------------------------------Borland.Delphi.System.pas--
Delphi.NET使用一个哈希表MetaTypeMap来缓存Token到元类的转换关系,
因为这种转换是耗时且较频繁的操作,这主要是为优化现有Delphi代码对元类的大量使用。
对一个Token,Delphi.NET先将其转换为一个Type类型,然后取其嵌套子类,
子类名就是@Meta前缀加类名,元类允许是公开或私有。
如果找到元类的类型,则从元类的@Instance字段获取值,也就是元类的一个实例;
否则使用此Token构造一个新的元类并返回。
这样Delphi.NET就完成了TClass机制在CLR环境下的映射。
//-----------------------------------------Borland.Delphi.System.pas--
type
TObject = System.Object;
_TClass = class;
TClass = class of TObject;
_TClass = class
protected
FInstanceType: System.RuntimeTypeHandle;
FClassParent: _TClass;
public
constructor Create; overload;
constructor Create(ATypeHandle: System.RuntimeTypeHandle); overload;
constructor Create(AType: System.Type); overload;
function ClassParent: TClass; virtual;
end;
TClassHelperBase = class(TObject)
public
FInstance: TObject;
end;
//-----------------------------------------Borland.Delphi.System.pas--
上一节我们大概分析过元类的实现原理。每一个类有一个对应的嵌套子类,
名称为@Meta前缀加上类名,此类从Borland.Delphi.System._TClass类继承出来,
在实现上类似TClassHelperBase,只不过FInstance是类一级的静态成员变量。
.class /*0200000D*/ auto ansi nested public beforefieldinit @MetaTDemo
extends Borland.Delphi.System.@TClass/* 02000003 */
{
.field /*0400000E*/ public static class HelloUnit.TDemo/* 02000005 *//@MetaTDemo/* 0200000D */ @Instance
.method /*06000027*/ private hidebysig specialname rtspecialname static
void .cctor() cil managed
.method /*06000026*/ public hidebysig specialname rtspecialname
instance void .ctor() cil managed
.method /*06000008*/ public instance void
Hello() cil managed
}
元类的静态构造函数如上一节中的@MetaTDemo..cctor()函数,构造一个元类的实例
放入元类的@Instance静态成员
private static TDemo.@MetaTDemo..cctor() {
TDemo.@MetaTDemo.@Instance = new @MetaTDemo..ctor();
}
元类的构造函数则载入自己类型的Token到FInstanceType字段中。
public TDemo.@MetaTDemo..ctor() : base() {
this.FInstanceType = Token of TDemo;
}
这个Token在CLR中起到索引的作用,用以在Metadata诸多表中定位特定的表项,
每种元素如类、方法、字段、属性等等都有其自己的Token。在BCL中Token表现为
RuntimeTypeHandle类型,用于诸如Type.GetTypeFromHandle之类函数,
可以通过Type.TypeHandle获取。
关于Token的重要性及物理实现上用法请参加前面提到的我对Metadata分析的文章。
元类这里保存的FInstanceType实际上就是类似于Delphi中VMT指针的索引。
//-----------------------------------------Borland.Delphi.System.pas--
constructor _TClass.Create;
begin
inherited Create;
end;
constructor _TClass.Create(ATypeHandle: System.RuntimeTypeHandle);
begin
inherited Create;
FInstanceType := ATypeHandle;
end;
constructor _TClass.Create(AType: System.Type);
begin
Create(AType.TypeHandle);
end;
//-----------------------------------------Borland.Delphi.System.pas--
可以看到_TClass的几种形式构造函数,实际上都是围绕着这个Token做文章。
//-----------------------------------------Borland.Delphi.System.pas--
function _TClass.ClassParent: TClass;
begin
if not Assigned(FClassParent) then
FClassParent := _TClass.Create(System.Type.GetTypeFromHandle(FInstanceType).BaseType.TypeHandle);
Result := FClassParent;
end;
//-----------------------------------------Borland.Delphi.System.pas--
而_TClass.FClassParent则是在需要时填充的父类的元类。注意这里的转换Token到
CLR中类型的方法。System.Type.GetTypeFromHandle函数和后面要使用到的
System.Type.GetTypeHandle函数完成Type与Token之间的双向转换。
因此可以说在Delphi.NET中,元类实际上就是对类的Token的一个封装。
在了解了元类的实现后,我们来看看如何从一个Token获取其元类。
//-----------------------------------------Borland.Delphi.System.pas--
var
MetaTypeMap: Hashtable;
function _GetMetaFromHandle(ATypeHandle: System.RuntimeTypeHandle): _TClass;
var
t: System.Type;
begin
if not Assigned(MetaTypeMap) then
MetaTypeMap := Hashtable.Create;
Result := _TClass(MetaTypeMap[ATypeHandle]);
if not Assigned(Result) then
begin
t := System.Type.GetTypeFromHandle(ATypeHandle);
t := t.GetNestedType(‘@Meta‘ + t.name, BindingFlags(Integer(BindingFlags.Public) or
Integer(BindingFlags.NonPublic)));
if Assigned(t) then
begin
Result := _TClass(t.GetField(‘@Instance‘).GetValue(nil));
MetaTypeMap.Add(ATypeHandle, Result);
end
else
begin
Result := _TClass.Create(ATypeHandle);
end;
end;
end;
//-----------------------------------------Borland.Delphi.System.pas--
Delphi.NET使用一个哈希表MetaTypeMap来缓存Token到元类的转换关系,
因为这种转换是耗时且较频繁的操作,这主要是为优化现有Delphi代码对元类的大量使用。
对一个Token,Delphi.NET先将其转换为一个Type类型,然后取其嵌套子类,
子类名就是@Meta前缀加类名,元类允许是公开或私有。
如果找到元类的类型,则从元类的@Instance字段获取值,也就是元类的一个实例;
否则使用此Token构造一个新的元类并返回。
这样Delphi.NET就完成了TClass机制在CLR环境下的映射。
Delphi.NET 内部实现分析(3.2)
Delphi.NET 内部实现分析(1)
Delphi.NET 内部实现分析(2)
Delphi.NET 内部实现分析(3.1)
Delphi.NET 内部实现分析(3.3)
Delphi.NET 内部实现分析(3.4)
Delphi.NET 内部实现分析(4)
Delphi.NET 内部实现分析(5)
Delphi.NET 内部实现分析(5)
Delphi.NET 内部实现分析(4)
Delphi.NET 内部实现分析(3.4)
PAM 的应用开发和内部实现源码分析
Delphi中PING的实现
Delphi和Java实现webservice
用DELPHI实现为NT添加用户
Delphi中PING的实现ewe
Delphi中PING的实现a
Delphi屏幕截图技术实现2
Delphi屏幕截图技术实现d
使用.NET实现断点续传
在Delphi中实现VFP6的查询速度 - Delphi - 文档中心 - 源码天空
浅析多层结构及其在Delphi中的实现<一>
Delphi中不使用第三方控件实现XP风格
DELPHI的RTTI实现数据集的简单对象化