没有简单的方法可以直接执行此操作,但是您可以使用一些技术来提高源代码和运行时性能的效率。一种方法可能是创建一个简单的助手来从给定的数据集中初始化适当类型的新值。
您可以为此使用记录方法,但这会使使用缓存的字段引用不那么优雅,因此我建议使用单独的专用初始化程序类。这可以使用缓存的字段引用来提高效率:
type
TPersonFDInitialiser = class
private
fldID: TIntegerField;
fldName: TStringField;
fldSurname: TStringField;
function get_NewValue: TPerson;
public
constructor Create(const aSource: TDataset);
property NewValue: TPerson read get_NewValue;
end;
在构造函数中缓存字段引用避免了每次检索每条记录的值时都必须按名称查找它们。为字段数据类型使用适当的类允许直接访问每个字段值而无需任何转换:
constructor TPersonFDInitialiser.Create(const aSource: TDataset);
begin
inherited;
fldID := aSource.FieldByName('id') as TIntegerField;
fldName := aSource.FieldByName('name') as TStringField;
fldSurname := aSource.FieldByName('surname') as TStringField;
end;
function TPersonFDInitialiser.get_NewValue: TPerson;
begin
result.ID := fldID.Value;
result.Name := fldName.Value;
result.Surname := fldSurname.Value;
end;
正如您所看到的,这不是大量的工作(比显式初始化 1 个记录值所需的工作量多一点),但使迭代使用更加优雅和更快地编写,看起来有点像这样:
recno := 0;
init := TPersonFDInitialiser.Create(qryPersons);
try
while NOT qryPersons.EOF do
begin
persons[recno] := init.NewValue;
qryPersons.Next;
Inc(recno);
end;
finally
init.Free;
end;
qryPersons
一些返回人员行的TFDQuery在哪里,并且persons
是您的TPerson记录数组(当然,大小/处理得当)
通过使用TDataset基类(TFDQuery最终派生自该基类),您可以在需要从TDataset后代初始化TPerson的任何地方使用此初始化程序类,无论是TFDQuery还是TClientDataset或其他任何东西(只要其中的字段数据集的命名是一致的,如所写,但如果需要,初始化程序可以在这方面更加灵活。这留作练习)。
走得更远
根据您的需要,可以进行许多增强来改进此类初始化程序类的实用性,例如:
// To initialise a one-off, new TPerson value from a data set use a
// class function which will internally create an initialiser, obtain
// a new TPerson then destroy the initialiser for you:
//
// Note that this will need to be overloaded if it has the same name as
// the instance method (which must also then be overloaded):
class function TPersonFDInitialiser.NewValue(const aSource: TDataset): TPerson; overload;
// Implement a procedure which will initialise an existing TPerson value
// (by reference) with values from the current record.
//
// Again, a class procedure overload could be provided for one-off use
// taking care of creating and freeing the required initialiser:
class procedure TPersonFDInitialiser.SetPerson(const aSource: TDataset; var aPerson: TPerson); overload;
procedure TPersonFDInitialiser.SetPerson(var aPerson: TPerson); overload;
注意:这些SetPerson
方法可以通过get_NewValue实际调用该方法的方式实现,这样您在整个实现中只有一个方法可以实际执行任何值设置。这将消除初始化代码的重复,提高初始化程序类的可靠性和可维护性:
function TPersonFDInitialiser.get_NewValue: TPerson;
begin
SetPerson(result);
end;
procedure TPersonFDInitialiser.SetPerson(var aPerson: TPerson);
begin
aPerson.ID := fldID.Value;
aPerson.Name := fldName.Value;
aPerson.Surname := fldSurname.Value;
end;