I'm trying to build an API, but I'm stopped at the following problem:
Here is all the code to simulate the problem
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Rtti;
type
TForm1 = class(TForm)
btnWorking: TButton;
btnNotWorking: TButton;
procedure btnWorkingClick(Sender: TObject);
procedure btnNotWorkingClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TEntityManagerWhereExpression = record
FCondition: Boolean;
end;
TEntityManagerWhereExpressionFnc = reference to function(): TEntityManagerWhereExpression;
TEntityExpressionOperation = record
private
FCondition: Boolean;
public
class operator Implicit(A: TEntityExpressionOperation): TEntityManagerWhereExpression;
class operator Equal(A, B: TEntityExpressionOperation): TEntityExpressionOperation;
class operator BitwiseAnd(A, B: TEntityExpressionOperation): TEntityExpressionOperation;
end;
TEntityExpression<T> = record
private
FValue: TValue;
public
class operator Implicit(A: string): TEntityExpression<T>;
class operator Implicit(A: TEntityExpression<T>): string;
class operator Equal(A, B: TEntityExpression<T>): TEntityExpressionOperation;
end;
IMyEntity = interface
['{BE3EE808-47BB-4E83-94BA-ABC9B3D861F2}']
function GetNome: TEntityExpression<string>;
property Nome: TEntityExpression<string> read GetNome;
end;
TMyEntity = class(TInterfacedObject, IMyEntity)
function GetNome: TEntityExpression<string>;
end;
IManager = interface
['{DE38CC69-069F-48F9-A9A4-E93BA0A87E5F}']
function produce(out myEntity: IMyEntity): IManager;
procedure Show(const exp: TEntityManagerWhereExpression);
end;
TMyManager = class(TInterfacedObject, IManager)
public
function produce(out myEntity: IMyEntity): IManager;
procedure Show(const exp: TEntityManagerWhereExpression);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnNotWorkingClick(Sender: TObject);
var
my: IMyEntity;
begin
TMyManager.Create().produce(my).Show(my.Nome = 'Paulo');
end;
procedure TForm1.btnWorkingClick(Sender: TObject);
var
my: IMyEntity;
MyManager: IManager;
begin
MyManager := TMyManager.Create().produce(my) as IManager;
MyManager.Show(my.Nome = 'Paulo 2');
end;
{ TMyManager }
function TMyManager.produce(out myEntity: IMyEntity): IManager;
begin
Result := Self;
myEntity := TMyEntity.Create;
end;
procedure TMyManager.Show(const exp: TEntityManagerWhereExpression);
begin
if exp.FCondition then
ShowMessage('true')
else
ShowMessage('false');
end;
{ TEntityExpressionOperation }
class operator TEntityExpressionOperation.BitwiseAnd(A, B: TEntityExpressionOperation): TEntityExpressionOperation;
begin
Result.FCondition := A.FCondition and B.FCondition;
end;
class operator TEntityExpressionOperation.Equal(A, B: TEntityExpressionOperation): TEntityExpressionOperation;
begin
Result.FCondition := False;
end;
class operator TEntityExpressionOperation.Implicit(A: TEntityExpressionOperation): TEntityManagerWhereExpression;
begin
Result.FCondition := A.FCondition;
end;
{ TEntityExpression<T> }
class operator TEntityExpression<T>.Equal(A, B: TEntityExpression<T>): TEntityExpressionOperation;
begin
Result.FCondition := A.FValue.AsString = B.FValue.AsString;
end;
class operator TEntityExpression<T>.Implicit(A: string): TEntityExpression<T>;
begin
Result.FValue := A;
end;
class operator TEntityExpression<T>.Implicit(A: TEntityExpression<T>): string;
begin
Result := A.FValue.AsString;
end;
{ TMyEntity }
function TMyEntity.GetNome: TEntityExpression<string>;
begin
Result := 'Paulo';
end;
end.
The problem is in the code snippet
TMyManager.Create (). Produces (my) .Show (my.Name = 'Paul');
where the variable my was not initialized, since the code snippet
my.name = 'Paulo'
is checked before
produce
the problem does not occur when I call it this way:
var
my: IMyEntity;
MyManager: IManager;
begin
MyManager: = TMyManager.Create (). Produces (my) as IManager;
MyManager.Show (my.Name = 'Paul 2');
because the variable my is initialized before calling the Show method
how can I prevent the variable my from being used before it is initialized?
Can someone help me solve this problem? thank you so much