Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi RTTI SetValue for Enumerations

How do I use RTTI to set an enumerated field's value ?

I.e.

type
  TCPIFileStatus= (fsUnknown, fsProcessed);
  TTest = class
    FStatus: TCPIFileStatus; 
  end;
      ...
  var
    Data: TTest;
    Ctx: TRttiContext;
    Status : TCPIFileStatus;
  begin
    Data := TTest.Create;
    Status := fsProcessed;
    Ctx.GetType(Data.ClassType).GetField('FStatus').SetValue(Data, Status);
  end;

I get "Invalid class typecast."
NB:I need to use RTTI because I will not always know the object type or field name at design time.

like image 283
David Moorhouse Avatar asked Feb 25 '23 17:02

David Moorhouse


2 Answers

you must pass a TValue to the SetValue method try using this code :

{$APPTYPE CONSOLE}
uses
  Rtti,
  SysUtils;


type
  TCPIFileStatus= (fsUnknown, fsProcessed);
  TTest = class
    FStatus: TCPIFileStatus;
  end;

  var
    Data   : TTest;
    Ctx    : TRttiContext;
    Status : TCPIFileStatus;
    v      : TValue;
begin
  try
    Data := TTest.Create;
    try
      Status := fsProcessed;
      v:= v.From(status); 
      Ctx.GetType(Data.ClassType).GetField('FStatus').SetValue(Data, v);

      // do your stuff
    finally
       Data.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
like image 107
RRUZ Avatar answered Mar 01 '23 23:03

RRUZ


Another solution to this problem, in the case you don't know the exact enum type on your function but instead it's TypeInfo, is to use TValue's Make procedure.

procedure Make(AValue: NativeInt; ATypeInfo: PTypeInfo; out Result: TValue); overload; static;

Here is an example (From an XML config parser): This is later used for a TRTTIField/TRTTIProperty.SetValue()

function EnumNameToTValue(Name: string; EnumType: PTypeInfo): TValue;
var
  V: integer;

begin
  V:= GetEnumValue(EnumType, Name);
  TValue.Make(V, EnumType, Result);
end;

Hope this helps you.

like image 39
podostro Avatar answered Mar 02 '23 00:03

podostro