Delphi:RTTI和TObjectList< TObject> [英] Delphi: RTTI and TObjectList<TObject>

查看:396
本文介绍了Delphi:RTTI和TObjectList< TObject>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据以前的一个答案 post ,我正在调查以下设计的可能性:

  TChildClass = class TObject)
private
FField1:string;
FField2:string;
end;

TMyClass = class(TObject)
private
FField1:TChildClass;
FField2:TObjectList< TChildClass>;
end;

现在,在现实世界中,TMyClass将有10个不同的列表,所以我想能够使用RTTI解决这些列表。但是,我对这个类的其他领域不感兴趣,所以我需要检查某个字段是否是某种TObjectList。这是我到目前为止:

  procedure InitializeClass(RContext:TRttiContext; AObject:TObject); 
var
ROwnerType:TRttiType;
RObjListType:TRttiType;
RField:TRttiField;
SchInf:TSchemaInfoDetail;
begin
ROwnerType:= RContext.GetType(AObject.ClassInfo);
RObjListType:= RContext.GetType(TObjectList< TObject>);
用于ROwnerType.GetFields中的RField开始
//如何检查TMyClass.FField2(它是TObjectList< TChildClass>)的类型是否是某种类型的TObjectList?
end;

显然, RField.FieldType<> RObjListType.FieldType 。但是,他们确实有一些关系,不是吗?看起来很可怕(也是错误的),为了使其非常可能地使得 RField.FieldType 实际上是一个 TObjectList



说实话,我对泛型非常不舒服,所以这个问题可能很天真。不过,我非常乐意学习。上述解决方案是否可能实施? TIA!

解决方案

每个泛型实例都是唯一的,与其他实例在RTTI方面没有任何关系。由于Delphi不能在运行时实例化泛型,所以不存在与例如.NET的 GetGenericTypeDefinition 。你可以做的最好的是看看这个类型的形状 - 例如它是否执行 GetEnumerator Add 等。

也可以足够灵活来处理一般的集合类型,而不仅仅是从 TObjectList< T> 实例化的集合类型。 C#与它的集合初始化器做类似的事情 - 它寻找一个 Add 方法并插入调用:

< a href =http://msdn.microsoft.com/en-us/library/bb384062.aspx =noreferrer> http://msdn.microsoft.com/en-us/library/bb384062.aspx


Based on one answer to an earlier post, I'm investigating the possibility of the following design

TChildClass = class(TObject)
private
  FField1:  string;
  FField2:  string;
end;

TMyClass = class(TObject)
private
  FField1:  TChildClass;
  FField2:  TObjectList<TChildClass>;
end;

Now, in the real world, TMyClass will have 10 different lists like this, so I would like to be able to address these lists using RTTI. However, I'm not interested in the other fields of this class, so I need to check if a certain field is some sort of TObjectList. This is what I've got so far:

procedure InitializeClass(RContext: TRttiContext; AObject: TObject);
var
  ROwnerType:   TRttiType;
  RObjListType: TRttiType;
  RField:       TRttiField;
  SchInf:       TSchemaInfoDetail;
begin
ROwnerType := RContext.GetType(AObject.ClassInfo);
RObjListType := RContext.GetType(TObjectList<TObject>);
for RField in ROwnerType.GetFields do begin
  // How do I check if the type of TMyClass.FField2 (which is TObjectList<TChildClass>) is some sort of TObjectList?
end;

Clearly, RField.FieldType <> RObjListType.FieldType. However, they do have some relation, don't they? It seems horrible (and wrong!) to make a very elaborate check for common functionality in order to make it highly probable that RField.FieldType is in fact a TObjectList.

To be honest, I am quite uncomfortable with generics, so the question might be very naïve. However, I'm more than happy to learn. Is the above solution possible to implement? TIA!

解决方案

Every generic instantiation is unique and has no relationship with other instantiations with respect to RTTI. Because Delphi can't instantiate generic types at runtime, there's no equivalent to e.g. .NET's GetGenericTypeDefinition. The best you can do is look at the shape of the type - e.g. does it implement GetEnumerator, Add etc.

This could also be flexible enough to handle general collection types, not just ones instantiated from TObjectList<T>. C# does something similar with its collection initializers - it looks for an Add method and inserts calls to it:

http://msdn.microsoft.com/en-us/library/bb384062.aspx

这篇关于Delphi:RTTI和TObjectList&lt; TObject&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆