我有一个TBuilder
继承自TObjectList
. TBuilder
可以执行 ADO 相关操作并使用结果填充其内部结构。除此之外,可以通过 HTTP 调用在 Web 上完成相同的操作。返回的结果也会被解析并更新内部结构。
从这里开始,我从数据库表生成 pas 文件以模仿其结构。假设我有一个名为 Company 的表,我以编程方式生成一个TCompany
对象,该对象也继承自TBuilder
该对象,然后可以选择需要的对象。目前,我TCompany
使用一种类型进行构造,该类型表示我希望它执行 ADO 操作或我希望它执行 HTTP 操作。TBuilder
然后通常会有一个加载过程,然后根据类型,它会生成 SQL 并从数据库(或 http)加载,并在内部用结果填充自己。
现在我要做的是拆分TBuilder
,以便一个单元知道如何通过 ADO 查询数据库,而另一个单元通过 HTTP 查询。我也在考虑继承这两个类TBuilder
。但我遇到了挑战,TCompany
因为它需要继承自TBuilder
, or TADOBuilder
or TDSBuilder
(后两个是新单位)。如果我继承TADOBuilder
它只能代表一种类型的对象。我正在努力做到这一点,以便TCompany
随时可以成为两者中的任何一个。我看到您只能使用接口实现多重继承,但我对此并不陌生,无法弄清楚如何重新设计它,以便我TCompany
可以同时成为两种类型的对象。
有什么想法可以解决这个问题吗?目前我被困在Delphi 6中。
这是它的外观:
TCompany = class(TBuilder) //I generate this programatically. This represents a table in the database
private
fUser: TSecurityUser;
function GetCompanyName: TBuilderField;
function GetCompanyAbbreviation: TBuilderField;
function GetCompanyID: TBuilderField;
function GetDateCreated: TBuilderField;
function GetDeleted: TBuilderField;
public
Property CompanyID:TBuilderField read GetCompanyID;
Property CompanyName:TBuilderField read GetCompanyName;
Property Abbreviation:TBuilderField read GetCompanyAbbreviation;
property DateCreated:TBuilderField read GetDateCreated;
property Deleted:TBuilderField read GetDeleted;
property User:TSecurityUser read fUser Write fUser;
constructor NewObject(psCompanyName,psAbbreviation:string);
constructor Create(conType:TConnectionType = conTypeSQLServer);override;
这就是 Load 过程的样子,此时我正试图以更智能的方式拆分成单独的单元:
function TBuilder.Load(psSQL:string = ''; poLoadOptions:TLoadOptions = []; poConnectionType:TConnectionType = conNone): Boolean;
var
LoQuery:TADOQuery;
LoSQL:string;
LoConnectionType:TConnectionType;
begin
Result := True;
LoConnectionType := fConnectionType;
if poConnectionType <> conNone then
LoConnectionType := poConnectionType;
if LoConnectionType = conTypeSQLServer then
begin
LoQuery := TADOQuery.Create(nil);
Try
try
LoQuery.Connection := uBuilder.ADOConnection;
LoSQL := psSQL;
if LoSQL = '' then
LoSQL := BuildSelectSQL;
LoQuery.SQL.Text := LoSQL;
LoQuery.Open;
LoadFromDataset(LoQuery);
except on E:exception do
begin
Error := E.Message;
Result := False;
end;
end;
Finally
FreeAndNil(LoQuery);
end;
end else
if fConnectionType = conTypeDatasnap then
begin
fWebCallType := sqlSelect;
try
if Assigned(fParent) then
if fParent.Error <> '' then
Exit;
if Assigned(OnBusyLoadingHook) then
OnBusyLoadingHook('Busy loading...');
{Reset the msg}
if Assigned(OnDisplayVisualError) then
OnDisplayVisualError(imtRed,'');
if (poLoadOptions <> LoadOptions) then
LoadOptions := LoadOptions + poLoadOptions;
Result := InternalLoad(loFullyRecursiveLoad in LoadOptions);
finally
{ We're done loading }
if Assigned(OnBusyLoadingHook) then
OnBusyLoadingHook('');
end;
end;
end;
然后我会以这种方式使用该对象:
var
LoCompany:TCompany;
begin
LoCompany := TCompany.Create(conTypeDatasnap);
LoCompany.CompanyName.Value := 'Test';
LoCompany.Load; //This will then generate the appropriate JSON and pass it via idhttp component to the server and the results will be parsed into its structure.
end;
如果我更改类型,它将直接查询数据库。