How do I find out whether a string value exists as a typed record named TEntity
I have a record which I named TEntity
type
TEntity = record
VariableName : string;
VariableValue : double;
end;
Mass : TEntity;
Force : TEntity;
Acceleration : TEntity;
ReturnedValue : string;
mystring : string;
Mass.VariableName := 'Mass';
Mass.VariableValue := 5;
I also have a string value which is returned from a function and that string value is placed inside returnedvalue.
returnedvalue := myfunction(mystring);
//returnedvalue is Mass
//returnedvalue = Mass
now I have records of type TEntity, how do I check dynamically during runtime 开发者_运维问答whether the word returned into returnedvalue exists as an TEntity. I need a function that is modular so it would work regardless of whether the sting is Mass or Acceleration etc.
Thanks,
Ben
If you want to keep track of all TEntity's in existence, you will have to add them to a list (or registry) of some sort and ensure that they are removed from there when they are removed from existence. Checking whether a string exists as a TEntity after that becomes trivial: just work through the list (or registry) to find it.
While instances of a class are created explicitedly and (unless referenced counted through interface implementations) freed explicitely, it may be easier to convert your TEntity to a class instead of a record, though it does have the drawback of no longer being able to do a Mass.VariableValue := 1
without creating the Mass first.
You may end up having to go this way though. Because, although records can have methods nowadays (not sure since which Delphi version) and you could add a constructor to register the entity to the list automatically, they unfortunately do not support destructors, so you cannot provide for automatic de-registration from the list.
Untested code, written in browser
type
TEntity = class(TObject)
private
FName: string;
FValue: Double;
public
constructor Create(const aName: string; const aValue: Double);
destructor Destroy; override;
property Name: string read FName write FName;
property Value: Double read FValue write FValue;
end;
function FindEntity(const aName: string): TEntity;
implementation
var
_EntityList: TObjectList;
constructor TEntity.Create(const aName: string; const aValue: Double);
begin
Assert(FindEntity(aName) = nil, 'Entity should not already be in the _EntityList');
_EntityList.Add(Self);
FName := aName;
FValue := aValue;
end;
destructor TEntity.Destroy;
begin
_EntityList.Extract(Self);
inherited Destroy;
end;
function FindEntity(const aName: string): TEntity;
begin
Result := nil;
for i := 0 to _EntityList.Count - 1 do begin
if SameText(TEntity(_EntityList[i]).Name, aName) then begin
Result := TEntity(_EntityList[i]);
Break;
end;
end;
end;
initialization
_EntityList := TObjectList.Create({aOwnsObjects=}False);
finalization
FreeAndNil(_EntityList);
Of course the FindEntity function should be optimized when you have more than a couple of entities in memory at the same time. First line of optimization would be to sort the list on the names and keep it sorted and to use a binary search to find specific entities.
You could derive TEntity from TInterfacedObject instead so that you get the benefits of reference counting and the instances being destroyed automatically when their reference count drops to zero. If you go that route, you would still have to create the instances explicitely. Also in this case you should not convert the _EntityList to an TInterfaceList, because that would mean the reference count can never drop to zero (adding an instance to the list increases the reference count by one)...
精彩评论