我知道这个标题非常不活泼。
我有一系列文本行,我需要按特定顺序对其执行特定操作。我想出了一种通过定义以下记录结构来实现此目的的方法:
TProcessOrderRecord = record
RecordTypes: TByteSet;
InitialiseProcedure: TPreScanProc;
ProcessProcedure: TProcessRecord;
FinaliseProcedure: TEndScanProc;
end;
AProcessOrderArray = array of TProcessOrderRecord;
初始化倾向于调用构造函数来填充宿主对象中的字段。
Process 将是对象上的一个过程,将为与 RecordTypes 中的记录类型之一匹配的每个文本行调用。
当 Finalise 知道完整的记录集已被处理时,它往往会调用析构函数并可能执行任何检查。
处理这个数组的方法非常简单:
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 的实例?
目前,我已经在主机对象上采用了“调用者”方法,然后可以在需要时调用 FMyObj 实例,但这会创建一个带有大量单行方法的相当臃肿的对象。
编辑以澄清/复杂化问题
有时,FObj
的一个实例可以处理多种类型的记录(通常如果它们具有主从关系)。在这种情况下,第一个记录类型的 InitialiseProcedure
将创建 FObj
,第二个记录类型的 FinaliseProcedure
将释放 FObj
并且每条记录的ProcessProcedure
可以引用FObj
的不同过程(do1
和do2
)。
最佳答案
At present I have resorted to having 'caller' methods on the host object which can then call the FMyObj instance when needed, but this is creating quite a bloated object with lots of single-line methods.
这是正确的解决方案。由于实例在初始化时不可用,因此您别无选择。
当您使用 of object
时,您正在定义一个名为 method pointer 的东西。 。当您分配给方法指针类型的变量时,实例将在分配点被捕获。没有机制可以动态解析与方法指针关联的实例。实现这一目标的唯一方法是使用运行时委托(delegate),这就是您当前正在做的事情。通常情况下,会使用另一层间接来解决问题!
包含许多方法的记录看起来非常像界面
。我怀疑最优雅的解决方案将涉及一个接口(interface)
。也许在调用时您可以调用一个返回接口(interface)
的函数。该函数将在调用时使用 FMyObj
的值来定位适当的接口(interface)。
关于delphi - 如何在对象存在之前将记录字段设置为 'Procedure of object'以便其可以运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15253864/