Reputation: 571
How to handle object references in datasnap server?
I have Datasnap server method which returns TUser object
TServerMethods.CurrentUser(const AId: Integer): TUser
begin
Result := GlobalCurrentUser; // <- Don't want to free this object
Result.AddReference;
end;
TUser in child class of TReferencedObject
TReferencedObject = class(TObject)
private
FReferenceCnt: integer;
public
procedure AddReference; virtual;
procedure RemoveReference; virtual; // Frees object if reference count goes to 0
property ReferenceCnt: integer Read FReferenceCnt Write FReferenceCnt;
end;
Currently DataSnap server Frees TUser object but I want to call RemoveReference for TReferencedObject descendants.
Upvotes: 1
Views: 575
Reputation: 571
I copied DataSnap files Data.DBXJSONReflect.pas and Datasnap.DSReflect.pas to project directory, add to project and made three modifications.
Two changes in Data.DBXJSONReflect to set correct ReferenceCount
1) TJSONUnMarshal.CreateObject
if HasObject(ObjId) then
begin
Obj := GetObject(ObjId);
if Obj is TReferencedObject then {Framework}
TReferencedObject(Obj).AddReference; {Framework}
exit(Obj);
end
2) TJSONPopulationCustomiser.PostPopulate
if Data is TReferencedObject then {Framework}
TReferencedObject(Data).AddReference; {Framework}
One change in Datasnap.DSReflect to release reference
1) TDsMethodValues.ClearReferenceParameters
changed FUserObject.Clear to ClearUserObjects(FUserObjects); and added local function
procedure ClearUserObjects(const AUserObjects: TObjectList<TObject>); {Framework}
var
i: Integer;
begin
FUserObjects.OwnsObjects := False;
for i := FUserObjects.Count - 1 downto 0 do
if FUserObjects.Items[i] is TReferencedObject then
begin
TReferencedObject(FUserObjects.Items[i]).RemoveReference;
FUserObjects.Delete(i);
end;
FUserObjects.OwnsObjects := True;
FUserObjects.Clear;
end;
Upvotes: 1