У меня есть базовый класс TBuilder
, который наследуется от TObjectList
. TBuilder
может выполнять операции, связанные с ADO, и заполнять его внутреннюю структуру результатами. В дополнение к этому, та же самая операция может быть сделана через Интернет, через вызовы HTTP. Возвращенные результаты также анализируются, а внутренняя структура обновляется.
С этого момента я генерирую файлы pas из таблицы базы данных, чтобы имитировать ее структуру. Скажем, у меня есть таблица с именем Company, я программно генерирую объект TCompany
, который также наследуется от TBuilder
, который затем может выбрать, каким он должен быть. На данный момент я создаю TCompany
с типом, который говорит, что я хочу, чтобы он выполнял операции ADO или я хотел, чтобы он выполнял операции HTTP. TBuilder
обычно будет иметь процедуру загрузки и, в зависимости от типа, будет генерировать SQL и загружаться из базы данных (или http) и заполнять себя результатами.
Теперь я пытаюсь разделить TBuilder
так, чтобы один модуль знал, как запрашивать базу данных через ADO, а другой - через HTTP. Я думал также унаследовать эти два класса от TBuilder
. Но меня бросает вызов TCompany
, потому что он должен наследоваться от TBuilder
, или TADOBuilder
, или 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;
Вот так выглядит процедура загрузки, в тот момент, когда я пытаюсь разбить ее на отдельные блоки более умным способом:
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;
Если я изменю тип, он напрямую запросит базу данных.