-2

I am using TMemIniFile to store configuration and I need to sort the sections in alpha order.

For that I have created a descendant of TMemIniFile

  TRWStudioMemIniFile = class(TMemIniFile)
  public
    procedure UpdateFile; override;
    procedure GetSortedStrings(List: TStrings);
  end;


{ TRWStudioMemIniFile }

procedure TRWStudioMemIniFile.GetSortedStrings(List: TStrings);
var
  I, J: Integer;
  Strings: TStrings;
begin
  List.BeginUpdate;
  try
    Sections.Sort;
    for I := 0 to Sections.Count - 1 do
    begin
      List.Add('[' + Sections[I] + ']');
      Strings := TStrings(Sections.Objects[I]);
      for J := 0 to Strings.Count - 1 do List.Add(Strings[J]);
      List.Add('');
    end;
  finally
    List.EndUpdate;
  end;
end;

procedure TRWStudioMemIniFile.UpdateFile;
var
  List: TStringList;
begin
  List := TStringList.Create;
  try
    GetSortedStrings(List);
    List.SaveToFile(FileName, Encoding);
  finally
    List.Free;
  end;
end;

but it needs to have access to the Sections (actually FSections: TStringList, that is a private member of TMemIniFile)

I have created a Helper class to expose that member thru a property. However this behavior is not supported anymore in Delphi 10.1

I started copy/paste the TMemIniFile to my unit and after and endless process I am ending up making a copy of the entire System.IniFile, just to access the FSections.

My question is how to access that FSections member without need to duplicate everything from that unit just to gain visibility

OR is there another way that I can Sort the Sections before saving? (I am just calling the TStringList.Sort from FSections)

Eduardo Elias
  • 1,742
  • 1
  • 22
  • 49
  • 4
    How about creating a new instance of `TMemIniFile` and adding the sections to it one by one in the order you want to have? – Ondrej Kelle Sep 15 '16 at 04:25
  • 1
    Order is not important in an ini file. Why do you need to do this at all. – David Heffernan Sep 15 '16 at 06:30
  • 2
    Order is usually not important in an ini file but sometimes it may be: for readability, documentation, or simply when the task is to keep it sorted to satisfy a client. It's a text format for a reason - to be readable/editable by humans. – Ondrej Kelle Sep 15 '16 at 08:26
  • 1
    It is possible to get the address of the private member `FSections` with help of `RTTI` if you want to go that route. – LU RD Sep 15 '16 at 08:32
  • @DavidHeffernan because my boss asked for that, what else is needed? – Eduardo Elias Sep 15 '16 at 11:46
  • Best bet is to use a bespoke INI parser/emitter then. Or persuade your boss that it doesn't matter. – David Heffernan Sep 15 '16 at 11:46
  • @OndrejKelle Exclty, this ini file is accessed by the customers and we need to keep it readable as possible. – Eduardo Elias Sep 15 '16 at 11:47
  • A helpful related question with multiple answers found here: http://stackoverflow.com/questions/36716363/how-to-access-private-methods-without-helpers – Jerry Dodge Sep 15 '16 at 14:07

1 Answers1

5

Rather than relying on type-casting and "cracking open" the private member, you can instead get the sections into your own TStringList using the inherited ReadSections() method, sort that list as needed, and then use the inherited ReadSectionValues() method to read the strings for each section:

var
  sections: TStringList;
  values: TStringList;
begin
  sections := TStringList.Create;
  try
    ReadSections(sections);
    sections.Sort;

    values := TStringList.Create;
    try
      List.BeginUpdate;
      try
        for I := 0 to sections.Count - 1 do
        begin
          List.Add('[' + sections[I] + ']');

          values.Clear; // Just in case
          ReadSectionValues(sections[i], values);

          for J := 0 to values.Count - 1 do
            List.Add(values[J]);
          List.Add('');
        end;
      finally
        List.EndUpdate;
      end;
    finally
      values.Free;
    end;
  finally
    sections.Free;
  end;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Deltics
  • 22,162
  • 2
  • 42
  • 70
  • 1
    *To whoever imposed their personal style on the code and removed [imho] important comments about the change from the OP referencing existing objects to the need to create/free ones:* If you could please refer me to the **official** "StackOverflow Delphi Coding Standard" I'll happily observe that standard in any future answer. If not, then by all means make suggestions for improvement or comments (it's what they are for) or if you believe your approach is substantively different and superior then by all means post it as a different answer. Otherwise kindly keep your hands to yourself. – Deltics Sep 15 '16 at 21:18
  • Your use of `try..finally` was not a question "style" or "coding standards. It was quite simply objectively ***wrong*** in the sense that it was used incorrectly for the purpose of resource protection. And even though your code was merely "demonstrative", it doesn't help to set bad examples. That aside, questions are publicly editable for a reason. When you contribute to this site, your work enters public domain. – Disillusioned Sep 16 '16 at 02:11
  • 1
    Not public domain, @Craig. Creative Commons. See section 3 of the terms of service. Deltics, you've been a member of this site for over seven years. I'm sorry if this is the first time you've had your contributions edited, but it really shouldn't take you by surprise by now. The ability to edit other people's posts is one of the primary reasons Stack Overflow was created. If you want to restore the deleted paragraph, go ahead, but please keep the other changes; they really make your original answer better. – Rob Kennedy Sep 16 '16 at 02:28