Delphi 如何将记录字段设置为';目标程序';在对象存在以便它可以运行之前

Delphi 如何将记录字段设置为';目标程序';在对象存在以便它可以运行之前,delphi,delphi-2006,Delphi,Delphi 2006,我知道这个标题很不时髦 我有一系列的文本行,我需要按照特定的顺序对它们执行特定的操作。通过定义以下记录结构,我想出了一种方法: TProcessOrderRecord = record RecordTypes: TByteSet; InitialiseProcedure: TPreScanProc; ProcessProcedure: TProcessRecord; FinaliseProcedure: TEndScanProc; end; AProces

我知道这个标题很不时髦

我有一系列的文本行,我需要按照特定的顺序对它们执行特定的操作。通过定义以下记录结构,我想出了一种方法:

TProcessOrderRecord = record
  RecordTypes:       TByteSet;
  InitialiseProcedure: TPreScanProc;
  ProcessProcedure:    TProcessRecord;
  FinaliseProcedure:   TEndScanProc;
end;

AProcessOrderArray = array of TProcessOrderRecord;
Initialise倾向于调用一个构造函数,该构造函数将填充宿主对象中的一个字段

进程将是对象上的一个过程,它将为与RecordTypes中的一个记录类型匹配的每一个文本行调用

Finalize将倾向于调用析构函数,并可能在知道已处理完整记录集时执行任何检查

处理此数组的方法非常简单:

procedure TImport.ScanTransferFile;
var
  i: integer;
  lArrayToProcess: AProcessOrderArray;
begin
  lArrayToProcess := SetUpProcessingOrder(NLPGApp.ImportType);
  for i := low(lArrayToProcess) to high(lArrayToProcess) do
  begin
    ProcessRecordType(lArrayToProcess[i].RecordTypes,     lArrayToProcess[i].InitialiseProcedure, lArrayToProcess[i].ProcessProcedure, lArrayToProcess[i].FinaliseProcedure);
  end;
end;

procedure TImport.ProcessRecordType(const RecordTypesToFind: TByteSet; PreScanProcedure: TPreScanProc; OnFindRecord: TProcessRecord; OnCompleteScan: TEndScanProc);
var
  lLineOfText: string;
  lIntegerRecordID: byte;
begin
  if Assigned(PreScanProcedure) then PreScanProcedure;
  try
    if assigned(OnFindRecord) then
    begin
      Reader.GoToStartOfFile;
      while not Reader.EndOfFile do
      begin
        lLineOfText := Reader.ReadLine;
        lIntegerRecordID := StrToIntDef(GetRecordID(lLineOfText), 0);
        if lIntegerRecordID in RecordTypesToFind then
        begin
          try
            OnFindRecord(lLineOfText);
          except
            on E: MyAppException do
            begin
            // either raise to exit or log and carry on
            end;
          end;
        end;
      end;
    end;
  finally
    // OnCompleteScan usually contains calls to destructors, so ensure it's called
    if Assigned(OnCompleteScan) then OnCompleteScan;
  end;
end;
我的问题是,我想将记录定义为:

RecordTypes = [10]
InitialiseProcedure = ProcToCreateFMyObj
ProcessProcedure = FMyObj.do
FinaliseProcedure = ProcToFreeFMyObj
这可以很好地编译,但是当调用ProcessProcedure时,由于设置ProcessProcedure时FMyObj是nil,所以即使现在设置了FMyObj,TMyObj的实例也是nil。有没有干净的方法让记录在调用时而不是在第一次分配时指向FMyObj的实例

目前,我已经求助于在主机对象上使用“caller”方法,然后在需要时调用FMyObj实例,但这会创建一个包含大量单行方法的臃肿对象

编辑以澄清/复杂问题

有时,
FObj
的一个实例可以处理多种类型的记录(通常如果它们具有主-详细关系)。在这种情况下,第一个记录类型的
InitialiseProcedure
将创建
FObj
,第二个记录的
FinaliseProcedure
将释放
FObj
,并且每个记录的
ProcessProcedure
可以引用
FObj
的不同过程(
do1
do2

目前,我已经求助于在主机对象上使用“caller”方法,然后在需要时调用FMyObj实例,但这会创建一个包含大量单行方法的臃肿对象

这是正确的解决办法。由于实例在初始化时不可用,因此您别无选择

当您使用对象的
时,您定义的是一种称为。分配给方法指针类型的变量时,实例将在分配点捕获。没有动态解析与方法指针关联的实例的机制。实现这一点的唯一方法是使用运行时委托,这是您当前正在做的事情。正如经常发生的情况一样,另一个间接层用于解决问题

包含许多方法的记录看起来非常像一个
接口
。我怀疑最优雅的解决方案将涉及
接口
。也许在调用时,您可以调用一个返回
接口的函数。该函数将在调用时使用
FMyObj
的值来定位适当的接口

目前,我已经求助于在主机对象上使用“caller”方法,然后在需要时调用FMyObj实例,但这会创建一个包含大量单行方法的臃肿对象

这是正确的解决办法。由于实例在初始化时不可用,因此您别无选择

当您使用对象的
时,您定义的是一种称为。分配给方法指针类型的变量时,实例将在分配点捕获。没有动态解析与方法指针关联的实例的机制。实现这一点的唯一方法是使用运行时委托,这是您当前正在做的事情。正如经常发生的情况一样,另一个间接层用于解决问题


包含许多方法的记录看起来非常像一个
接口
。我怀疑最优雅的解决方案将涉及
接口
。也许在调用时,您可以调用一个返回
接口的函数。该函数将在调用时使用
FMyObj
的值来定位相应的接口。

是的,可以对记录进行额外的运行时初始化:

var
  A: TProcessOrderRecord;

begin
  ..
  TMethod(A.ProcessProcedure).Data:= FMyObj;
  ..
end;

尽管我更喜欢一个不同的解决方案,比如您已经使用的解决方案。

是的,可以对您的记录进行额外的运行时初始化:

var
  A: TProcessOrderRecord;

begin
  ..
  TMethod(A.ProcessProcedure).Data:= FMyObj;
  ..
end;

尽管我更喜欢一个不同的解决方案,就像您已经使用的解决方案一样。

-1这从来都不是一个好主意。如果您手头有
FMyObj
,那么您应该只分配整个方法指针。我同意这应该是可行的(在询问之前,我发现一篇web文章做了类似的事情),然而,正如您所说,我认为另一种解决方案是首选的,因为它不是Delphi语言的一个众所周知的方面,而且如果我是唯一一个查看代码的人,并且代码是相当静态的,那就没问题了。@MattAllwood为什么要这样做?如果你可以这样做,你可以这样做:
A.ProcessProcedure:=FMyObj.ProcessProcedure
@MattAllwood-我曾经有过一个想法,就是“拆分”数据并对方法的各个部分进行编码,以获得更紧凑的解决方案,但最终还是更喜欢“臃肿”的解决方案解决方案更清晰,可维护性更好-请参见。@David-同意相同的反思-无论哪种方式都会使试图在一开始就建立整个结构的做法无效-1这绝不是一个好主意。如果您手头有
FMyObj
,那么您应该只分配整个方法指针。我同意这应该是可行的(在询问之前,我发现一篇web文章做了类似的事情),然而,正如您所说,我认为另一种解决方案是首选的,因为它不是Delphi语言的一个众所周知的方面,而且如果我是唯一一个查看代码的人,并且它是fa的话,这也没关系