如何a)迭代Delphi(西雅图)TObjectList和/或TList对象并访问索引处的对象
我正在创建一个Datasnap服务器和客户机集,最终用它将服务器连接到几个不同的数据库。对于服务器,我创建了一个名为TMember的测试类。服务器和客户端使用此单元uMember 在服务器上,我放置了一个函数,用于创建一个TMember并将其返回给请求的客户机。TMember对象中的一些数据是从SQL Server数据库收集的 在客户端,我在客户机主窗体上创建了一个TObjectList类型的全局变量。每次启动createnewmember函数时,都会在服务器上创建对象,并成功地将其发送回客户端。我可以访问对象方法和属性 然而,我的问题是迭代这个TObjectList集合。不管我怎么做,我只得到AVs。下面是我的代码尝试。有人能指出我把事情搞砸了吗 提前非常感谢 以下是TMember接口:如何a)迭代Delphi(西雅图)TObjectList和/或TList对象并访问索引处的对象,delphi,datasnap,delphi-10-seattle,Delphi,Datasnap,Delphi 10 Seattle,我正在创建一个Datasnap服务器和客户机集,最终用它将服务器连接到几个不同的数据库。对于服务器,我创建了一个名为TMember的测试类。服务器和客户端使用此单元uMember 在服务器上,我放置了一个函数,用于创建一个TMember并将其返回给请求的客户机。TMember对象中的一些数据是从SQL Server数据库收集的 在客户端,我在客户机主窗体上创建了一个TObjectList类型的全局变量。每次启动createnewmember函数时,都会在服务器上创建对象,并成功地将其发送回客户端
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;