Можно ли сделать более чистым этот код Delphi, связанный с массивом функций объекта? - PullRequest
1 голос
/ 18 июня 2020

Относительно этой функции в Delphi:

function TAudioFileMetadata.LoadTags(const Filename: String; var LastError: Integer; var DetectedFormat: TAudioFormat): Boolean;
type
  TLoadFromFunction = function (const Filename: String; var LastError: Integer): Boolean of object;

  TLoadFrom = record
    Format: TAudioFormat;
    Process: TLoadFromFunction;
  end;

var
  i: Byte;
  LoadOrder: array [1..6] of TLoadFrom;

begin
  DetectedFormat := afUnknown;

  LoadOrder[1].Format := afMp3;
  LoadOrder[1].Process := LoadFromMp3;

  //...

  LoadOrder[6].Format := afApe;
  LoadOrder[6].Process := LoadFromApe;

  for i := Low(LoadOrder) to High(LoadOrder) do
  begin
    Result := LoadOrder[i].Process(Filename, LastError);
    if Result then
    begin
      DetectedFormat := LoadOrder[i].Format;
      break;
    end;
  end;
end;

Как я могу улучшить свою реализацию? Могу ли я создать / заполнить массив LoadOrder за один раз (или, по крайней мере, не использовать 2 строки на TLoadFrom)? Можно ли использовать массив const (я так не думаю)?

1 Ответ

3 голосов
/ 18 июня 2020
Замыкания

Delphi (function|procedure ... of object) поддерживаются записью TMethod, которой вы можете управлять во время выполнения. Так что попробуйте что-нибудь вроде этого:

function TAudioFileMetadata.LoadTags(const Filename: String; var LastError: Integer; var DetectedFormat: TAudioFormat): Boolean;
type
  TLoadFromFunction = function (const Filename: String; var LastError: Integer): Boolean of object;

  TLoadFrom = record
    Format: TAudioFormat;
    ProcessAddr: Pointer;
  end;

const
  LoadOrder: array[1..6] of TLoadFrom = (
    (Format: afMp3; ProcessAddr: @TAudioFileMetadata.LoadFromMp3),
    ...
    (Format: afApe; ProcessAddr: @TAudioFileMetadata.LoadFromApe)
  );

var
  i: Byte;
  Process: TLoadFromFunction;

begin
  DetectedFormat := afUnknown;
  TMethod(Process).Data := Self;

  for i := Low(LoadOrder) to High(LoadOrder) do
  begin
    TMethod(Process).Code := LoadOrder[i].ProcessAddr;

    Result := Process(Filename, LastError);
    if Result then
    begin
      DetectedFormat := LoadOrder[i].Format;
      Exit;
    end;
  end;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...