Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何a)迭代Delphi(西雅图)TObjectList和/或TList对象并访问索引处的对象_Delphi_Datasnap_Delphi 10 Seattle - Fatal编程技术网

如何a)迭代Delphi(西雅图)TObjectList和/或TList对象并访问索引处的对象

如何a)迭代Delphi(西雅图)TObjectList和/或TList对象并访问索引处的对象,delphi,datasnap,delphi-10-seattle,Delphi,Datasnap,Delphi 10 Seattle,我正在创建一个Datasnap服务器和客户机集,最终用它将服务器连接到几个不同的数据库。对于服务器,我创建了一个名为TMember的测试类。服务器和客户端使用此单元uMember 在服务器上,我放置了一个函数,用于创建一个TMember并将其返回给请求的客户机。TMember对象中的一些数据是从SQL Server数据库收集的 在客户端,我在客户机主窗体上创建了一个TObjectList类型的全局变量。每次启动createnewmember函数时,都会在服务器上创建对象,并成功地将其发送回客户端

我正在创建一个Datasnap服务器和客户机集,最终用它将服务器连接到几个不同的数据库。对于服务器,我创建了一个名为TMember的测试类。服务器和客户端使用此单元uMember

在服务器上,我放置了一个函数,用于创建一个TMember并将其返回给请求的客户机。TMember对象中的一些数据是从SQL Server数据库收集的

在客户端,我在客户机主窗体上创建了一个TObjectList类型的全局变量。每次启动createnewmember函数时,都会在服务器上创建对象,并成功地将其发送回客户端。我可以访问对象方法和属性

然而,我的问题是迭代这个TObjectList集合。不管我怎么做,我只得到AVs。下面是我的代码尝试。有人能指出我把事情搞砸了吗

提前非常感谢

以下是TMember接口:

    type
  TMember = class
    FFirstName : String;
    FLastName : String;
    FFullname : String;
    FAddress : String;
  private
    {private declarations}
  public
    {public declarations and properties}
    constructor Create(fname, lname : String); overload;
    constructor Create(otherMember : TMember); overload;
    destructor Destroy;
    procedure SetFName(const Value: String);
    procedure SetFullname(const Value: String);
    procedure SetLName(const Value: String);
    function GetFullname : String;
    function ToString : String;
    procedure ChangeAddr(Addr : String);

    property Name : String read FFirstName write SetFName;
    property Surname : String read FLastName write SetLName;
    property Fullname : String read GetFullname write SetFullname;
  end;
此代码用于从服务器创建新的TMember对象:

    procedure TfrmMainClient.btnCreateMemClick(Sender: TObject);
var
  Server : TServerMethodsClient;
  newMem : TMember;
  i : Integer;
begin
  try
    Server := TServerMethodsClient.Create(DM1.ServerConn.DBXConnection);
    newMem := Server.GetMember(edtFName.Text, '');
    if Assigned(newMem) then begin
      AllMembers.Add(newMem);
      Listbox1.Items.Add(newMem.GetFullname);
    end;

  finally
    Server.Free;
  end;
end;
因此,过了一段时间,客户端内存中有几个对象在浮动。现在我想从列表框中访问它们,就好像它是一个菜单,可以从中选择一个TMember。其思想是记录Listbox的ItemIndex,并将其发送到AllMember TObjectList对象集合,以访问位于该索引处的TMember。这创造了一个可爱的小AV。于是,我尝试了在ObjectList上进行一次简单的迭代,使用一个基本的for..do循环来填充一个列表框。同样的结果。我还尝试了一个for..in循环,但没有成功

我很确定我只是错过了一些愚蠢的事情

以下是尝试1:

    procedure TfrmMainClient.btnRefreshClick(Sender: TObject);
var
  nextMember : TMember;
begin
  for nextMember in AllMembers do
    begin
      Listbox1.Items.Add(nextMember.GetFullname);
    end;
end;
以下是尝试2:

    procedure TfrmMainClient.btnRefreshClick(Sender: TObject);
var
  nextMember : TMember;
  i : Integer;
begin
  for i := 0 to AllMembers.Count - 1 do
    begin
      nextMEmber := TMember.Create(AllMembers[i]);
      Listbox1.Items.Add(nextMember.GetFullname);
    end;
end;
以下是尝试3:

    procedure TfrmMainClient.btnRefreshClick(Sender: TObject);
var
  nextMember : TMember;
  i : Integer;
begin
  for i := 0 to AllMembers.Count - 1 do
    begin
      nextMember := AllMembers.Items[i];
      Listbox1.Items.Add(nextMember.GetFullname);
    end;
end;
我相信有人能帮忙

编辑1:

改变这个

 procedure TfrmMainClient.btnRefreshClick(Sender: TObject);
var
  i: Integer;
  Item : TPair<Integer, TMember>;
  ActiveMember : TMember;
  Key : Integer;
begin
  Listbox1.Clear;
  for i := 0 to AllMembersKeys.Count - 1 do
    begin
      try
        ActiveMember := TMember.Create('','');

        //Get the MemberID as a Key stored in AllMembersKeys
        Key := AllMembersKeys[i];

        //Now try get this TMember record from the AllMembers collection
        if AllMembers.TryGetValue(Key, ActiveMember) then
          if ActiveMember <> nil then
            Listbox1.Items.Add(ActiveMember.GetFullname)
        else
          Listbox1.Items.Add('Could not locate TMember with Key: ' + IntToStr(Key));
      finally
        ActiveMember.Free;
      end;
    end;
end;

从更改所有成员的类型

TObjectList<TMember> 

旁白:构造函数必须在try之前出现,否则构造函数中的异常会导致您对未初始化的引用调用Free。至于这个问题,缺少大量详细信息。从GetMember返回的对象。谁拥有它?谁负责摧毁它?什么是所有成员?OwnsObjects设置为True的TObjectList。这听起来像是一个需要解决的问题。Server.GetMemeber是如何实现的?正如@David所说,请提供MCVE。否则会有太多的猜测。调试你的程序。为类创建一个空的重写析构函数。在其上放置断点并运行代码。检查调用堆栈并查看何时以及由谁调用析构函数非常感谢您的帮助。它可以工作,但当我试图回顾性地迭代TDictionary以读回它当前包含的对象时,仍然会遇到AVs。我尝试使用它自己的迭代器TPair,但访问TMember键。它的值部分仍然会导致AV。我怎样才能做到最好?或者,我应该回避完整的对象,而是选择记录吗?你能把代码添加到你的问题中吗?你是如何循环列表的。您是如何创建列表的?当你释放列表时?他们不允许我把代码放在这里,所以我会尝试把它放在其他地方,不知道在哪里,尽管。。。
TObjectList<TMember> 
TDictionary<Integer, TMember>
procedure TfrmMainClient.btnCreateMemClick(Sender: TObject);
var
  Server : TServerMethodsClient;
  newMem : TMember;
  Idx : Integer;
begin
  try
    Server := TServerMethodsClient.Create(DM1.ServerConn.DBXConnection);
    newMem := Server.GetMember(edtFName.Text, '');
    if Assigned(newMem) then begin
      Idx := Listbox1.Items.Add(newMem.GetFullname);
      AllMembers.Add(Idx, newMem);
    end;
  finally
    Server.Free;
  end;
end;