首页 > 其他分享 >Delphi的TValue探索

Delphi的TValue探索

时间:2023-05-06 16:48:22浏览次数:38  
标签:探索 Delphi Value RecValue Writeln TValue TRect RecData

一、TValue结构

TValue定义在System.Rtti.pas

通过调用Make(...),将任意类型数据转换为TValue
通过调用ExtractRawData(...), ExtractRawDataNoCopy(...)将TValue转换为任意数据类型,两者区别是ExtractRawDataNoCopy转换时在堆中申请内存的数据,而ExtractRawData是安全的。
GetReferenceToRawData返回数据的指针,也是堆内存的指针。

二、类型转换为TValue

program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, Windows, TypInfo,Rtti;

var
IntData : Integer;
IntValue : TValue;

RecData : TRect;
RecValue : TValue;

begin
IntData := 1234;
TValue.Make(@IntData,TypeInfo(Integer),IntValue); //Integer类型也可以直接调用 IntValue := IntData; 这里演示TValue.Make
Writeln(IntValue.ToString);
RecData.Left := 10;
RecData.Right := 20;
TValue.Make(@RecData,TypeInfo(TRect),RecValue);
Writeln(RecValue.ToString);
readln;
end.

三、TValue转换到类型

在反序列化(反持久化)时,如果知道数据类型,可以调用下面的方法生成一个与此类型相应的TValue空记录:

TValue.Make(nil,TypeInfoVar,OutputTValue);
通过ExtractRawData,可以将TValue数据直接转换某类型数据:

program Project2;
{$APPTYPE CONSOLE}
uses SysUtils, Windows, TypInfo,Rtti;

var
RecData : TRect;
RecDataOut : TRect;
RecValue : TValue;

begin
RecData.Left := 10;
RecData.Right := 20;
TValue.Make(@RecData,TypeInfo(TRect),RecValue); //将TRect结构的RecData转换为TValue类型的RecValue

RecValue.ExtractRawData(@RecDataOut); //将TValue 结构数据转换成TRect类型数据
Writeln(RecDataOut.Left);
Writeln(RecDataOut.Right);

readln;
end.

四、通过TValue的访问类型的成员变量

TValue转换自某个类型后,可以使用的GetReferenceToRawData()获取数据指针,通过调用SetValue和GetValue读写
某个成员的值。

program Project3;
{$APPTYPE CONSOLE}
uses SysUtils, Windows, TypInfo,Rtti;

var
RecData : TRect;
RecValue : TValue;
Ctx : TRttiContext;

begin
Ctx := TRttiContext.Create;
// 创建空的、与TRect对应的TValue结构体,
TValue.Make(nil,TypeInfo(TRect),RecValue);
// 设置 Left 、 Right 成员变量值,使用TValue中成员变量的地址指针
Ctx.GetType(TypeInfo(TRect)).GetField('Left').SetValue(RecValue.GetReferenceToRawData,10);
Ctx.GetType(TypeInfo(TRect)).GetField('Right').SetValue(RecValue.GetReferenceToRawData,20);
// 转换为TRect结构体数据
RecValue.ExtractRawData(@RecData);
Writeln(RecData.Left);
Writeln(RecData.Right);
readln;
Ctx.Free;
end.

五、泛型转换函数

我们上面的例子,通过调用Make函数来转换成TValue,以及通过ExtractRawData转换成需要的类型,
Delphi还提供了泛型转换函数,可以指定已知的类型,直接进行转换:

class function From<T>(const Value: T): TValue; static;
function AsType<T>: T;
function IsType<T>: Boolean;
function TryAsType<T>(out AResult: T): Boolean;
function Cast<T>: TValue; overload;

program Project4;
{$APPTYPE CONSOLE}
uses SysUtils, Windows, TypInfo,Rtti;

var
RecData : TRect;
RecDataOut : TRect;
RecValue : TValue;
begin
RecData.Left := 10;
RecData.Right := 20;

RecValue := TValue.From<TRect>(RecData); //直接转换成 TValue

Writeln(RecValue.IsType<TRect>);

RecDataOut := RecValue.AsType<TRect>; //TValue直接转换成TRect

Writeln(RecDataOut.Left);
Writeln(RecDataOut.Right);
readln;
end.

六、数组

如果TValue转换自数组类型,则可以调用一下方法:

function GetArrayLength: Integer;
function GetArrayElement(Index: Integer): TValue;
procedure SetArrayElement(Index: Integer; const AValue: TValue);
我可以先定义数组类型后,再定义变量,则可以转换到TValue:

type
TIntArray = array of Integer;
var
IntArray : TIntArray;
// 或者
IntArray : TArray<Integer>; //在 System.pas 定义: TArray<T> = array of T;

七、Variant

Variant与TValue的转换容易产生混淆,调用TValue.FromVariant(),并不是将Varaint转换为TValue:

program Project5;
{$APPTYPE CONSOLE}
uses SysUtils, TypInfo,Rtti;

var
vExample : Variant;
Value : TValue;
begin
vExample := 'Hello World';
Value := TValue.FromVariant(vExample); //
writeln(GetEnumName(TypeInfo(TTypeKind),Ord(Value.Kind)));
Writeln(value.ToString);

vExample := 1234;
Value := TValue.FromVariant(vExample);
writeln(GetEnumName(TypeInfo(TTypeKind),Ord(Value.Kind)));
Writeln(value.ToString);

readln;
end.

如果希望将Variant转换为TValue,可以使用这个方法:

program Project6;
{$APPTYPE CONSOLE}
uses SysUtils, TypInfo,Rtti;

var
vExample : Variant;
Value : TValue;
begin
vExample := 'Hello World';
Value := TValue.From<variant>(vExample);
writeln(GetEnumName(TypeInfo(TTypeKind),Ord(Value.Kind)));
Writeln(value.AsType<variant>);

vExample := 1234;
Value := TValue.From<variant>(vExample);
writeln(GetEnumName(TypeInfo(TTypeKind),Ord(Value.Kind)));
Writeln(value.AsType<variant>);

readln;
end.

标签:探索,Delphi,Value,RecValue,Writeln,TValue,TRect,RecData
From: https://www.cnblogs.com/lucken2000/p/17377847.html

相关文章

  • [软件工程]关于SEMAT方法的思考和银弹问题的探索
    2013年4月底,应邀参加了首届中国软件质量高峰论坛,期间详细听了Jacobson公司的SEMAT的方法论。此后思考了很长时间,因为一直感觉没有考虑成型,所以,迟迟没有发表任何相关的文字出来,今天有了一点思考,决定将之发布出来,与大家共享片段,更多的内容还要等后续有时间之后的总结。SEMAT方法,Ivar......
  • 面向万物智联的应用框架的思考和探索(下)
     原文:https://mp.weixin.qq.com/s/tH1WcAhWwxmfU2FxKnT4ew,点击链接查看更多技术内容。应用框架,是操作系统连接开发者生态,实现用户体验的关键基础设施。其中,开发效率和运行体验是永恒的诉求,业界也在持续不断的发展和演进。本文重点围绕移动应用框架,梳理其关键发展脉络,并分析......
  • delphi 互斥量,只允许运行一个实例
    效果图: 代码超简单的:procedureTFrmLogin.FormCreate(Sender:TObject);varFmutex:THandle;begin//创建一个命名的互斥量,确保同一时间只有一个实例在运行//第三个参数是自定义的,随便取的,但一定要是唯一的标识FMutex:=CreateMutex(nil,True,'MyDelphiAppMutex')......
  • 面向万物智联的应用框架的思考和探索(中)
     原文:https://mp.weixin.qq.com/s/i-ddVaC0iBVXq4t12hz6-Q,点击链接查看更多技术内容。 应用框架,是操作系统连接开发者生态,实现用户体验的关键基础设施。其中,开发效率和运行体验是永恒的诉求,业界也在持续不断的发展和演进。本文重点围绕移动应用框架,梳理其关键发展脉络,并分......
  • 探索时代风口,别错过了小程序,再错过元服务
    “依托鸿蒙分布式特征,打破不同设备系统间壁垒,经过智慧化升级,蘑菇棚室相关种植环境参数能够在手机、平板等设备的服务卡片上实时显示……”“借助HarmonyOS的多样化卡片,一课表能够在设备桌面上随意设置与堆叠,直观呈现,帮助学生快速查看上课时间和地点,为成千上万人提供方便……”“......
  • 探索AI的无线可能|一图读懂金蝶云苍穹技术开放日第五期!
    4月28日,以“AIGC时代,探索AI的无限可能”为主题的金蝶云·苍穹技术开放日第五期完美收官。此次活动,围绕“RPA、ML和生成式AI”等方向赋能开发者,四位老师的精彩分享共计吸引了2058名开发者在线观看。关于本次活动分享的内容,你是不是还有不少疑问?RPA的架构及应用?如何实现智能销售预测?......
  • 面向万物智联的应用框架的思考和探索(上)
     原文:https://mp.weixin.qq.com/s/G6o6xSAWroz0fJK7oShYLA,点击链接查看更多技术内容。 应用框架,是操作系统连接开发者生态,实现用户体验的关键基础设施。其中,开发效率和运行体验是永恒的诉求,业界也在持续不断的发展和演进。本文重点围绕移动应用框架,梳理其关键发展脉络,并分......
  • DevOps探索 搭建企业镜像私服Harbor
    一、安装Docker及docker-compose1安装Docker#1、切换镜像源[root@master~]#wgethttps://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo-O/etc/yum.repos.d/docker-ce.repo#2、查看当前镜像源中支持的docker版本[root@master~]#yumlistdocker-ce-......
  • CeMeta神秘黑盒空间亮相AWE,AI黑科技探索新人机时代
    2023年4月27日-30日,AWE展会在上海新国际博览中心召开,国内外最具影响力、科技力的企业及智能科技产品重磅登场。开展首日,一个神秘的黑盒空间在W4馆揭开帷幕,与旁边纯白色的华为展台形成鲜明对比,透过入口处的三角门,可以看到展台中矗立着一块块科技感十足的屏幕,AI数字人在屏幕中现身互......
  • Delphi原子操作函数介绍
    一、Delphi的原子操作函数在System.SyncObjs单元中,有一个TInterlocked的密封类,其十多个类函数(classfunction)其实都是调用的System单元的原子操作函数,只是封装得更容易理解。使用方法:如对一个数值加一,则直接b:=TInterlocked.Increment(a);或TInterlocked.Increment(a);,不用创建......