将组件名称存储为字符串以备后用

Storing Component Name as a String for later use

在我的表单上有许多 TMyQuery 组件。他们的名字表明他们与哪些 MySQL Table 合作。例如,COMPONENTSTABLE 与 COMPONENTS TABLE 等一起使用

大约有 30 个 table,但将来可能会改变。

我还使用基本字符串列表从名为 TIMESTAMPS 的 Table 中读取字段名称。当更新、插入或删除发生时,此 table 通过触发器更新。 TIMESTAMPS Table 中的每个字段都指的是 Table 被修改的地方。 table中只有一条记录!根据字段值,我可以看到哪些 table 发生了变化,因此我可以刷新它而不是全部刷新。

我不想这样做;

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

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

{ and so on forever }

我想做的是;

现在我有一个 "Names / Values" 的字符串列表。每个 "Name" 都是 Table 中的字段名,"Value" 是由 MySQL 触发器提供的时间戳。

我有以下内容;

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;

我的字符串列表正在运行,名称、值等都是正确的。

我的问题是这样的;

有没有一种方法可以使用字符串("Names" 列表中的列)来引用一个对象(如果该对象存在)?

我已经有了一个函数,我可以通过将对象传递给它来刷新个人 table,但这是一个对象并且易于使用。我想根据从字符串中检索到的名称传递 "Object"。

我希望这是有道理的,你可以按照我的要求去做。

我不确定你的问题到底是什么。在答案的第一部分,我假设您并不真正关心对象的名称,而是想要一些自动化的方法来获取所有可用的 table 引用另一个 table 中的字段。在此之下,如果您知道对象的名称,我将回答您关于引用该对象的问题。

自动处理所有 tables

这取决于 class 你的对象是什么。

根据您的描述,我假设您的 TMyQuery 是表单拥有的 TComponent 后代。然后解决方案非常简单,因为每个 TComponent 都有一个 public Name 和一个拥有的组件列表 Components。然后你可以使用这样的东西:

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;

请注意,您可能需要添加额外的检查,例如确保 MyQuery.Name 不为空或者它作为字段存在于 TimeStampsTable.

如果您的对象只有 TObject,则没有 "standard" 名称 属性,也没有这些对象的标准注册。名称可以处理,显然您的组件已经有一个,所以这只是一个适当的类型强制的问题,但对象注册是另一回事。您可能必须为所有已创建的 TMyQuery 个实例创建某种全局列表。

根据对象的名称获取对象实例

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;

或者您可以简单地遍历所有 Components 并使用您自己的 Name 匹配。

虽然@pepak 接受的答案的第一部分不是我要找的(我以前在应用程序中使用过类似的代码,但发现它很慢),但答案的第二部分指出了我的意思正确的方向。

我(感谢 Pepak)的最终解决方案是;

Function RefreshQueryByName(Const Name: String): Boolean;
   Var
      Obj: TComponent;
   Begin
      Result := False;
      Obj := Self.FindComponent(Name);
      If Obj <> nil Then
         If Obj Is TMyQuery Then
            With Obj As TMyQuery Do
               If Active Then
               Begin
                  Refresh;
                  Result := True;
               End;
   End;

我通过传递从字段值中获取的字符串来使用它,该字段值标识我要刷新的 table。

现在,我的数据库应用程序会自动刷新其他用户更改的 table。它现在将刷新被其他用户修改的 30 个 table 中的任何一个,而不刷新所有 table。

感谢Pepak的帮助,我已经接受了你的回答,希望对其他人有用。