Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi RTTI: Wie kann ich prüfen, ob ein Feld vom Typ einer Klasse ist? (https://www.delphipraxis.net/180119-rtti-wie-kann-ich-pruefen-ob-ein-feld-vom-typ-einer-klasse-ist.html)

Der schöne Günther 24. Apr 2014 11:56

Delphi-Version: XE5

RTTI: Wie kann ich prüfen, ob ein Feld vom Typ einer Klasse ist?
 
Und ich dachte, ich könnte mit der RTTI umgehen.

Folgendes:
Delphi-Quellcode:
type
   TBaseClass = class(TObject);
   TSubClass = class(TBaseClass);

   TMyContainer = class
      first: TBaseClass;
      second: TSubClass;
      third: TObject;
   end;
Ich möchte alle Felder in
Delphi-Quellcode:
TMyContainer
finden, die zuweisungskompatibel zu
Delphi-Quellcode:
TBaseClass
sind. Also
Delphi-Quellcode:
first
und
Delphi-Quellcode:
second
.

Wie tue ich das? Mir fällt nichts anderes ein, als nur strikt Typ mit Typ vergleichen zu können.

Folgengender Code
Delphi-Quellcode:
var
   context: TRttiContext;
   fieldIterator: TRttiField;

begin
   context := TRttiContext.Create();

   for fieldIterator in context.GetType(TMyContainer).GetFields() do begin
      WriteLn( 'Feld gefunden: '+fieldIterator.Name.QuotedString() );

      if fieldIterator.FieldType = context.GetType(TBaseClass) then
         WriteLn('Das Feld ist eine zu TBaseClass kompatible Instanz');

      if Assigned(fieldIterator.FieldType.BaseType) then
         WriteLn('BaseType-Name: '+fieldIterator.FieldType.BaseType.Name);

      WriteLn(EmptyStr);
   end;

   ReadLn;
end.
ergibt
Code:
Feld gefunden: 'first'
Das Feld ist eine zu TBaseClass kompatible Instanz
BaseType-Name: TObject

Feld gefunden: 'second'
BaseType-Name: TBaseClass

Feld gefunden: 'third'
Man sieht:
  • TBaseClass leitet sich ab von TObject
  • TSubClass leitet sich ab von TBaseClass
  • TObject leitet sich von nichts ab

Nur: Muss ich jetzt für jedes Feld die gesamte Vererbungshierarchie bis
Delphi-Quellcode:
TObject
hochkrabbeln um zu schauen, ob meine gewollte Basisklasse einmal vorkommt?

Frage: Gibt es in der RTTI nichts wie das normale
Delphi-Quellcode:
InheritsFrom(..)
bzw. den
Delphi-Quellcode:
is
-Operator?

Der schöne Günther 24. Apr 2014 12:11

AW: RTTI: Wie kann ich prüfen, ob ein Feld vom Typ einer Klasse ist?
 
PS: Das in eine Helfer-Klasse zu packen war jetzt kein Ding, aber mir kommt es trotzdem komisch vor. Gibt es da nichts fertiges in der RTTI?


Delphi-Quellcode:
unit RttiTypeHelper;

interface

uses System.Rtti;

type
   TRttiTypeHelper = class helper for TRttiType
      private const
         Para_inheritsFromType_includeCurrent = True;

      public
         function inheritsFromType(
            const    baseType:    TRttiType;
            const  includeCurrent: Boolean = Para_inheritsFromType_includeCurrent
         ): Boolean; overload;

         function inheritsFromType(
            const    baseClass:    TClass;
            const  includeCurrent: Boolean = Para_inheritsFromType_includeCurrent
         ): boolean; overload;
   end;

implementation

function TRttiTypeHelper.inheritsFromType(
   const    baseType:    TRttiType;
   const  includeCurrent: Boolean = Para_inheritsFromType_includeCurrent
): Boolean;
var
   currentClassType: TRttiType;
begin
   Result := False;

   if not includeCurrent then
      currentClassType := self.baseType
   else
      currentClassType := self;

   while (not Result) and Assigned(currentClassType) do begin
         if currentClassType = baseType then
            Result := True;
         currentClassType := currentClassType.baseType;
      end;
end;

function TRttiTypeHelper.inheritsFromType(
   const    baseClass:    TClass;
   const  includeCurrent: Boolean = Para_inheritsFromType_includeCurrent
): Boolean;
var
   rttiContext: TRttiContext;
begin
   rttiContext := TRttiContext.Create();
   Result := inheritsFromType( rttiContext.GetType(baseClass), includeCurrent);
end;

end.

Uwe Raabe 24. Apr 2014 12:27

AW: RTTI: Wie kann ich prüfen, ob ein Feld vom Typ einer Klasse ist?
 
Delphi-Quellcode:
      if fieldIterator.FieldType.IsInstance then begin
        if fieldIterator.FieldType.AsInstance.MetaclassType.InheritsFrom(TBaseClass) then begin
          WriteLn('Das Feld ist eine zu TBaseClass kompatible Instanz');
        end;
      end;

Der schöne Günther 24. Apr 2014 12:52

AW: RTTI: Wie kann ich prüfen, ob ein Feld vom Typ einer Klasse ist?
 
Genau das! :thumb:

Herzlichen Dank. Wesentlich kürzer :-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:50 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz