How can i set (change) the value(s) of an TRttiSetType

I require to modify object set properties at runtime. I have been able to get as far as retrieving the Set values as below but I cannot figure out how to modify the set.

(Ptx is the TRttiProperty and has already been passed as a TRttiSetType)
var
	LType: TRttiSetType;
	Ctx: TRttiContext;
	LOrd: TRttiOrdinalType;
	LNames: Vector<string>;
begin
	LType := Ctx.GetType(Ptx.TypeInfo) as TRttiSetType;
	LOrd := LType.ElementType as TRttiOrdinalType;
	LNames.Assign((LOrd as TRttiEnumerationType).GetNames);
      ShowMessage(String.Join('|', LNames.Data));
end;

How can i modify or assign new values to the property Ptx?

Why? What is the actual problem you are trying to solve?

The Rtti props classes for properties all have a SetValue method - which takes a TValue - creating a TValue from a set should be a call to TValue.From - ymmv depending on delphi version.

You can also just use the old System.TypInfo functions to do it - sometimes that is simpler.

My software relies heavily on rtti and I’m using GetValue/ SetValue everywhere except when a tkSet property is encountered. An example is TStyleElements [seFont, seClient, seBorder].
Currently, I can read ToString (a method for all TObject) and get the text representation ie ‘[seFont,seBorder]’. However, I want to be able to set TStyleElements (or any other set property) from a text representation. As far as I can tell, there isn’t even a straightforward way of saving a set property to Json other than the ToString value.

This might help

unit VSoft.Core.Utils.Sets;

{ DUnit Tested in ..\Tests\TestVSoftSetUtils.pas }

interface
uses
  TypInfo,
  Windows;

type
  TSetUtils = class
  public
    class function SetToStringFB(const ATypeInfo: PTypeInfo; const Value): string;
    class function StringToSetFB(const ATypeInfo: PTypeInfo; const Value: string): Integer;
  end;

implementation
uses
  SysUtils;

class function TSetUtils.SetToStringFB(const ATypeInfo: PTypeInfo; const Value): string;
var
  I: Integer;
  Data: PTypeData; // set's type data
  EnumInfo: PTypeInfo; // set's base type info
  EnumData: PTypeData; // set's base type data
begin
  if ATypeInfo.Kind <> tkSet then
    Result := ''
  else
  begin
    Data := GetTypeData(ATypeInfo);
    EnumInfo := Data^.CompType^;
    EnumData := GetTypeData(EnumInfo);

    Assert(EnumInfo.Kind in [tkEnumeration, tkInteger]);

    Result := '[';
    for I := EnumData.MinValue to EnumData.MaxValue do
      if I in TIntegerSet(Value) then
      begin
        // The element is in the set, so add its name to the string.
        if Length(Result) > 1 then
          Result := Result + ','; // separate items with commas
        Result := Result + GetEnumName(EnumInfo, I);
      end;
    Result := Result + ']';
  end;
end;

class function TSetUtils.StringToSetFB(const ATypeInfo: PTypeInfo; const Value: string): Integer;
var
  P: PChar;
  EnumName: string;
  EnumValue: Longint;
  Data: PTypeData; // set's type data
  EnumInfo: PTypeInfo; // set's base type info

  // grab the next enum name
  function NextWord(var P: PChar): string;
  var
    i: Integer;
  begin
    i := 0;
    // scan til whitespace
    while not (SysUtils.CharInSet(P[i],[',', ' ', #0, ']'])) do
      Inc(i);
    SetString(Result, P, i);

    // skip whitespace
    while SysUtils.CharInSet(P[i],[',', ' ', ']']) do
      Inc(i);

    Inc(P, i);
  end;

begin
  Result := 0;
  if Value = '' then Exit;
  P := PChar(Value);
  Data := GetTypeData(ATypeInfo);
  EnumInfo := Data^.CompType^;

  // skip leading bracket and whitespace
  while SysUtils.CharInSet(P^, ['[', ' ']) do
    Inc(P);
  EnumName := NextWord(P);
  while EnumName <> '' do
  begin
    EnumValue := GetEnumValue(EnumInfo, EnumName);
    if EnumValue < 0 then
      raise Exception.Create('Invalid Enum Value!');
    Include(TIntegerSet(Result), EnumValue);
    EnumName := NextWord(P);
  end;
end;

end.

usage

    Byte(FVisibleColumns) := TSetUtils.StringToSetFB(TypeInfo(TLogFrameColumns), sColumnSet);

Note the cast there - not sure if that is still needed, haven’t touched this code in a long time.

Thanks Vincent. I seems that the new RTTI doesn’t provide an elegant solution as yet. I’m wondering if Spring4D has anything to assist? Thanks for your help.
Gerard

It may well do, the code I posted was written a long time ago - before the new Rtti code. The new rtti code is written using the old rtti as a base - so the older api is still quite valid to use.