反射机制初探
# Delphi反射机制初探
在Java中存在着一种强大的功能就是反射,所以我在考虑Delphi出来这么多年了,难道没有支持反射机制吗?经过翻山越岭的一顿搜索终于找到了反射的身影
在Delphi中反射称为RTTI(Run-Time Type Information) 翻译过来的名称是"运行期类型信息",也就是说可以在运行期获得数据类型或类(class)的信息
反射在我们普通程序开发中基本使用不到,但是在我们底层的程序设计中使用特别广泛,例如代理模式、工厂模式等一些设计模式,包括我们使用的开发工具以及各大开源框架底层都使用到了反射的原理。
# 初识反射
反射,从这个"反"字可以看出与我们平时正常的使用逻辑肯定不一样,那么到底什么地方不一样了?想要了解"反",就得先了解一下"正"的概念。
在正常情况下,如果要使用一个类,必须要经过以下几个步骤:
- 使用uses导入类所在的单元
- 通过构造方法(Create)进行类对象实例化
- 产生对象可以使用"对象.属性"进行类中属性的调用
- 通过"对象.函数()"调用类中的函数
在反射中,使用一个类并不需要导入类的所在单元,只要知道类的完整路径就可以知道该类中的所有信息
此外在Delphi中并不是所有的类都会存储到Rtti中的.只有那些在函数或类中被引用过的对象才会被自动添加到Rtti中,如果你想强制将所有的类都加入到Rtti中,那么只需要一个简单的预编译命令就可以了{$STRONGLINKTYPES ON}
uses rtti, System.StrUtils;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
Ctx: TRttiContext;
list: TArray<TRttiType>;
typ: TRttiType;
instance: TRttiInstanceType;
QRClass: TClass;
metodo: TRttiMethod;
begin
Self.Memo1.Clear;
Ctx := TRttiContext.Create;
//该方法需要{$STRONGLINKTYPES ON}指令的支持
//Ctx.FindType('Unit2.TPersion').Name;
//获取运行期类型
typ := Ctx.GetType(TPersion);
// 获取运行期类型实例
instance := typ.AsInstance;
//通过运行期实例获取引用类型
QRClass := instance.MetaclassType;
//获取构造方法
metodo := instance.GetMethod('Create');
//通过构造方法获取对象
Self.Memo1.Lines.Add(metodo.Invoke(QRClass, []).ToString);
//调用方法
typ.GetMethod('show').Invoke(metodo.Invoke(QRClass, []), []);
Ctx.Free;
end;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
- 上面的代码仅仅是作为一个示例,演示了反射的方式调用对象中函数的过程,更多的功能需要我们自己去摸索学习
RTTI相关信息并不多,我在调用其他单元类创建对象的时候一直在报错,翻遍无数的网页才在一个老外的提问中查到需要添加预编译指令,顺便吐槽一下现在网上的博客基本上都互相抄袭很少有原创内容,当我们翻山越岭的找到了以为是解决办法的文章时,一看内容全是一样的.....
最后:"老牛自知夕阳晚,不用扬鞭自奋蹄"与君共勉!