Search code examples
delphidelphi-7

Storing Component Name as a String for later use


On my form I have a number of TMyQuery Components. Their names identify which MySQL Tables they work with. For example, COMPONENTSTABLE works with the COMPONENTS TABLE, etc.

There are about 30 tables, but that might change in the future.

I also use a basic String List to read field names from a Table called TIMESTAMPS. This table is updated via triggers when an UPDATE, INSERT, or DELETE occurs. Each field within the TIMESTAMPS Table refers to which Table was modified. There's only one record in the table! Based on the field values I can see which table changed so I can refresh it rather than refreshing all of them.

I don't want to do this;

If fieldbyname['COMPONENTSTABLE'] <> CurrentTimeStamp
 then ComponentsTable.Refresh;

If fieldbyname['ORDERSTABLE'] <> CurrentTimeStamp
 then OrdersTable.Refresh;

{ and so on forever }

What I want to do is;

Right now I have a String List with "Names / Values". Each "Name" is the Fieldname within the Table and "Value" is the TIMESTAMP provided by MySQL Triggers.

I've got the following;

For Idx := 0 to MyStringList.Count -1 do
  Begin

    If MyStringlist.ValueFromIndex[Idx] <> SomethingElse then 
     Begin
        with (MyStringList.Names[Idx] as tMyQuery).Refresh;
     End;

  End;

I've got the String List functioning, the Names, the Values etc are all correct.

My question is this;

Is there a way I can use a String ("Names" column in the list) to refer to an Object if that Object exists?

I already have a function I use to refresh individual tables by passing an Object to it, but that's an Object and easy to work with. I'd like to pass the "Object" based on it's name retrieved from a String.

I hope this makes sense and you can follow what I'm after.


Solution

  • I am not sure what your question actually is. In the first part of the answer I assume that you don't really care about names of the objects but rather want some automated way of getting all the tables available refer to a field in another table. Below that, I answer your question about referring to an object if you know its name.

    Automated way of handling all tables

    It depends on what class your objects are.

    From your description, I assume your TMyQuery are TComponent descendants owned by the form. Then the solution is very simple, as each TComponent has both a public Name and a list of owned components Components. You can then use something like this:

    var
      i: integer;
      MyQuery: TMyQuery;
    begin
      for i := 0 to Pred(MyForm.ComponentCount) do
        if MyForm.Components[i] <> TimeStampsTable then
          if MyForm.Components[i] is TMyQuery then
          begin
            MyQuery := TMyQuery(MyForm.Components[i]);
            if TimeStampsTable.FieldByName(MyQuery.Name).AsDateTime >= LastAccess then ...
          end;
    end;
    

    Note that you may want to add extra checks, e.g. to make sure that MyQuery.Name is not empty or that it exists as a field in TimeStampsTable.

    If your objects are only TObjects, then there is no "standard" name property and no standard registration of these objects. Name can be handled, apparently your component already has one so it's just a question of a proper type coercion, but object registration is a different matter. You may have to create some kind of a global list for all your created TMyQuery instances.

    Getting an object instance based on that object's name

    function TMyForm.GetQueryByName(const Name: string): TMyQuery;
    var
      Obj: TObject;
    begin
      Result := nil;
      Obj := Self.FindComponent(Name);
      if Obj <> nil then
        if Obj is TMyQuery then
          Result := TMyQuery(Obj);
    end;
    

    Or you could simply loop over all Components and use your own Name matching.