The goal is to create a type called TURLString to be called as follows:
var
newURl : TURLString;
begin
newURL.Append('http://').Append('www.thehost.com').Append('path/on/server').Append('?');
...lots of app logic...
newURL.AppendParam('name', 'value').Append('#').AppendParam('name', 'value');
...more params added...
result := httpClient.Get(newURL);
end;
With TURLString defined like this (note its a record):
//from actual code used
TURLString = record
private
FString : string;
public
function Append(APart : string) : TURLString;
function AppendParam(AParam, AValue : string) : TURLString;
end;
function TURLString.Append(APart: string) : TURLString;
begin
FString := FString + APart;
result := self;
end;
function TURLString.AppendParam(AParam, AValue: string): TURLString;
begin
if (not Empty) then
FString := FString + URL_AMB;
FString := FString + AParam + '=' + AValue;
result := self;
end;
When stepping through the fluid calls, the values are appended but when exiting they revert to the first string passed into the first append call and newURL is equal to 'http://' while debugging the append call you see 'http://www.thehost.com/path/on/server?name=value#name=value'.
Is this concept possible with a record?
To get rid of the performance and memory use problem of record copy, you may use pointers as results type for your methods:
type
PURLString = ^TURLString;
TURLString = record
private
FString : string;
public
function Append(const APart : string) : PURLString;
function AppendParam(const AParam, AValue : string) : PURLString;
end;
function TURLString.Append(const APart: string) : PURLString;
begin
FString := FString + APart;
result := @self;
end;
function TURLString.AppendParam(const AParam, AValue: string): PURLString;
begin
if FString <> '' then
FString := FString + URL_AMB;
FString := FString + AParam + '=' + AValue;
result := @self;
end;
So you may be able to call your original TURLString just as wished:
newURL.Append('http://').Append('www.thehost.com').Append(...
And don't forget the const
keyword for string parameters of methods.
Note that the proper way of using a pointer should have been
newURL.Append('http://')^.Append('www.thehost.com')^.Append(...
but in fact the Delphi compiler is clever enough to add the ^ sign implicitly.
With this trick, you don't have to create nor free your newURL
instance. Note that only reference-counted parameters (string, variants, interfaces) will be initialized on the stack: integers or doubles will be pure random.
This is exactly what I used for creating some RTF content in my SynProject documentation tool (at least in the first versions, now I use a class instead of a record, since I wanted to add inheritance).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With