忽略這個使用Aurelius框架的事實,這個問題更多的是關於如何重新調整代碼以使這兩種類型的泛型構造函數注入都可以工作:
<字符串>
和
< TCustomConnection>
還忽略了一個事實,孩子的對象是在同一個單位,我一般把他們自己,但這恰恰使得它更容易在發帖提問。什麼是構造這個通用對象創建的正確方法
我想使用工廠方法模式來確定它應該在運行時進行什麼類型的連接,具體取決於我實例化的對象。 目前,它正在對創建期望的鏈接類型進行硬編碼。
在這個例子中,我想傳遞一個TModelDatabaseLink,但想要在運行時決定它可能是什麼類型的數據庫連接,或者數據庫連接是否來自一個文件。 是的,我知道我可以取消註釋FFilename,只是用它來保存文件名版本,但我總是有興趣學習更多。我想如果可能的話做,
unit Model.Database.Connection;
interface
uses
System.Classes,
Data.DB,
Aurelius.Drivers.Interfaces,
Aurelius.Engine.DatabaseManager;
type
TModelDatabaseLink<T> = class
private
//FFilename: string;
FConnection: T;
FOwnsConnection: boolean;
OwnedComponent: TComponent;
end;
TModelDatabaseConnection = class abstract
private
FDatabaseLink: TModelDatabaseLink<TCustomConnection>;
FDatabaseManager: TDatabaseManager;
FConnection: IDBConnection;
function CreateConnection: IDBConnection; virtual; abstract;
procedure CreateDatabaseManager;
public
constructor Create(ADatabaseLink: TModelDatabaseLink<TCustomConnection>);
destructor Destroy; override;
property Connection: IDBConnection read FConnection;
end;
TSQLLiteConnection = class(TModelDatabaseConnection)
private
function CreateConnection: IDBConnection; override;
end;
TFireDacConnection = class(TModelDatabaseConnection)
private
function CreateConnection: IDBConnection; override;
end;
implementation
uses
System.SysUtils,
Aurelius.Drivers.Base,
Aurelius.Drivers.SQLite,
Aurelius.Drivers.FireDac,
FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.VCLUI.Wait,
FireDAC.Comp.Client;
{ TModelDatabaseConnection }
constructor TModelDatabaseConnection.Create(ADatabaseLink: TModelDatabaseLink<TCustomConnection>);
begin
FDatabaseLink := ADatabaseLink;
FConnection := CreateConnection;
if Assigned(FConnection) then
CreateDatabaseManager
else
raise Exception.Create('Failed to open database');
end;
procedure TModelDatabaseConnection.CreateDatabaseManager;
begin
FDatabaseManager := TDatabaseManager.Create(FConnection);
end;
destructor TModelDatabaseConnection.Destroy;
begin
FDatabaseManager.Free;
FDatabaseLink.Free;
inherited Destroy;
end;
{ TSQLLiteConnection }
function TSQLLiteConnection.CreateConnection: IDBConnection;
var
LFilename: String;
LAdapter: TSQLiteNativeConnectionAdapter;
begin
//LFileName := FDatabaseLink.FConnection; << needs to be type string
LAdapter := TSQLiteNativeConnectionAdapter.Create(LFilename);
LAdapter.DisableForeignKeys;
Result := LAdapter;
end;
{ TFireDacConnection }
function TFireDacConnection.CreateConnection: IDBConnection;
var
LAdapter: TFireDacConnectionAdapter;
begin
if Assigned(FDatabaseLink.OwnedComponent) then
LAdapter := TFireDacConnectionAdapter.Create(FDatabaseLink.FConnection as TFDConnection, FDatabaseLink.OwnedComponent)
else
LAdapter := TFireDacConnectionAdapter.Create(FDatabaseLink.FConnection as TFDConnection, FDatabaseLink.FOwnsConnection);
Result := LAdapter;
end;
end.
的另一件事就是修改兩處作品:
LAdapter := TSQLiteNativeConnectionAdapter.Create(LFilename)
LAdapter := TFireDacConnectionAdapter.Create(FDatabaseLink.FConnection as TFDConnection, FDatabaseLink.OwnedComponent)
在父TModelDatabaseConnection使用抽象「GetAdapterClass」類型的功能,只是聲明類的適配器的孩子做這樣的事情:
LAdapter := GetAdapterClass.Create...
適配器聲明的一個例子是
TFireDacConnectionAdapter = class(TDriverConnectionAdapter<TFDConnection>, IDBConnection)
難道你正在使用Spring.Persistence適配器嗎?因爲這段代碼對我來說看起來很熟悉。如果是這樣,請查看Spring.Persistence.Core.ConnectionFactory.pas注入適配連接的不同ctor參數的方式。 –
嘿Stefan。實際上,這些實際上是TMS Aurelius框架中的那些。不過,我會看看Spring的單元,就像我在PC上看到的那樣,看看它是否給了我更多的線索。 – mikelittlewood
嗨Stefan。在Spring.Persistence.Adapters.SQLite中,您指定必須傳遞TSQLiteDatabase而不僅僅是文件名。在Spring代碼中唯一可以找到的是.. \ Marshmallow \ External \ SQLite3。這是一個「官方」春季嗎? – mikelittlewood