Reputation: 794
I have tested my own class with the dependency injection and now I have to implement it into production. The following is an excerpt of my class and relevant interface:
ITableDB = interface
['{171DE959-8604-4CD3-ACEA-ACCE15E95621}']
procedure Close;
procedure Open;
...
end;
TNewStrategy=class(TObject)
private
FTableDB: ITableDB
.....
public
constructor Create (ATableDB: ITableDB....)
end;
Instead of mocks and stubs I have to provide the class the real objects now. These are a number of third part components I have placed in a form at design time. Here one example:
type
TForm1 = class(TForm)
ThirdyPartDBTable1: ThirdyPartDBTable;
NewStrategy: TNewStrategy;
private
{ Private declarations }
public
{ Public declarations }
end;
How can I pass ThirdyPartDBTable1 to TNewStrategy.Create ? I tried the following code:
TMyThirdyPartDBTable = class(ThirdyPartDBTable, IITableDB)
public
procedure Close;
procedure Open;
...
end;
But when I try to change ThirdyPartDBTable1: ThirdyPartDBTable
into ThirdyPartDBTable1: TMYhirdyPartDBTable;
the compiler changes the reference TMYhirdyPartDBTable back to ThirdyPartDBTable.
Upvotes: 1
Views: 164
Reputation: 595329
In the code you showed, TNewStrategy
is not derived from TComponent
, so it cannot be placed on a TForm
at design-time. You would have to create it at run-time, in which case you have access to its constructor and can pass ThirdyPartDBTable1
to it, eg:
procedure TForm1.FormCreate(Sender: TObject);
begin
NewStrategy := TNewStrategy.Create(ThirdyPartDBTable1);
end;
However, if TNewStrategy
were a TComponent
descendant available at design-time, you could link ThirdyPartDBTable1
to NewStrategy
at design-time if you change TNewStrategy
to expose an ITableDB
property instead of passing it in the constructor, eg:
TNewStrategy = class(TComponent)
private
FTableDB: ITableDB
.....
public
constructor Create(AOwner: TComponent); override;
published
property TableDB: ITableDB read FTableDB write FTableDB;
end;
As long as ThirdyPartDBTable
implements ITableDB
then the Object Inspector and DFM streaming will allow it.
Update: since ThirdPartyDBTable
does not implement ITableDB
, you can use an interceptor class to implement it, eg:
interface
uses
..., ThirdPartyUnit;
type
ThirdyPartDBTable = class(ThirdPartyUnit.ThirdyPartDBTable, ITableDB)
public
procedure Close;
procedure Open;
end;
TForm1 = class(TForm)
ThirdyPartDBTable1: ThirdyPartDBTable;
NewStrategy: TNewStrategy;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
procedure ThirdyPartDBTable.Close;
begin
...
end;
procedure ThirdyPartDBTable.Open;
begin
...
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
NewStrategy := TNewStrategy.Create(ThirdyPartDBTable1 as ITableDB);
end;
end.
Upvotes: 2
Reputation: 54772
You cannot change the class of a component that you've put at design time by modifying it in the form declaration, the IDE owns the declarations in the upper public part of the form.
You can create your derived component at run time instead, or install it in a run time package and register with the component library. For a single time job, or for testing purposes, you can use an interposer class. In the below example I used a TPanel
since I don't have any ThirdyPartDBTable
, so be sure to put a panel on the test form. Also omitted the 'Close' method for brevity.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
ITableDB = interface
['{171DE959-8604-4CD3-ACEA-ACCE15E95621}']
procedure Open;
end;
TPanel = class(extctrls.TPanel, ITableDB)
public
procedure Open;
end;
TNewStrategy=class(TObject)
private
FTableDB: ITableDB;
public
constructor Create(ATableDB: ITableDB);
end;
TForm1 = class(TForm)
Button1: TButton;
Panel1: TPanel;
procedure Button1Click(Sender: TObject);
private
NewStrategy: TNewStrategy;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TPanel }
procedure TPanel.Open;
begin
ShowMessage('Open what?');
end;
{ TNewStrategy }
constructor TNewStrategy.Create(ATableDB: ITableDB);
begin
FTableDB := ATableDB;
end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
NewStrategy := TNewStrategy.Create(Panel1 as ITableDB);
NewStrategy.FTableDB.Open;
end;
end.
Upvotes: 0