开发者

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)...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜