Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi: RTTI and TObjectList<TObject>

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!

like image 892
conciliator Avatar asked Feb 28 '23 06:02

conciliator


1 Answers

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

like image 167
Barry Kelly Avatar answered Mar 08 '23 10:03

Barry Kelly