【问题标题】:Add a Data Pointer to TIdTCPServer and TIdCustomTCPServer添加指向 TIdTCPServer 和 TIdCustomTCPServer 的数据指针
【发布时间】:2026-01-13 15:30:02
【问题描述】:

我想添加一个指向TIdTCPServer 的数据指针,并且我想在TIdCustomTCPServer 中也有它。我不擅长覆盖等,所以这就是我到目前为止所拥有的:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdContext, IdBaseComponent, IdComponent,
  IdCustomTCPServer, IdTCPServer, Vcl.StdCtrls;

type
  TIdTcpServer = class(IdTcpServer.TIdTcpServer)
  public
    Data : Pointer;
end;

type
  TForm1 = class(TForm)
    IdTCPServer1: TIdTCPServer;
    Button1: TButton;
    procedure IdTCPServer1Connect(AContext: TIdContext);
    procedure IdTCPServer1Disconnect(AContext: TIdContext);
    procedure IdTCPServer1Execute(AContext: TIdContext);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  IdTCPServer1.Data := TObject (12345); // Just a test to fill the Data Pointer;
end;

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
var
  ParentServer  : TIdCustomTCPServer;
  MyData        : Integer;
begin
 //
 ParentServer   := TIdServerContext(AContext).Server;
 // MyData      := Integer(ParentServer.Data);
end;

procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
begin
 //
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
 //
end;

end.

我怎样才能让数据指针回到任何 OnConnect/OnDisconnect/etc ?

【问题讨论】:

标签: delphi indy indy10 delphi-xe4


【解决方案1】:

http://www.indyproject.org/docsite/html/!!MEMBEROVERVIEW_TIdTCPServer.html 中没有 Data 属性 - 您确定您的代码可以编译并工作吗?

好吧,如果有这样的属性,那么只需将变量强制转换回来。

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
var
  ParentServer  : TIdCustomTCPServer;
  MyData        : Integer;
begin
 //
 ParentServer   := TIdServerContext(AContext).Server;
 MyData      := Integer( (ParentServer as TIdTcpServer).Data);
end;

如果没有 - 那么您有两个选择。一是子类化——在你的类中添加属性,二是添加一些外部数据存储。

Unit IDWithData;
interface uses IdTCPServer;

type TIdTcpServer = class( IdTCPServer.TIdTcpServer )
      public
        var Data: Integer;
     end;
implementation
end.

将此单元添加到TForm1 的单元接口/使用列表中的最后一个位置,瞧!服务器现在 - 对 IDE 不可见 - 被您的子类替换,它具有新的 Data 字段,因此上面的类型转换将使用这个新的但有意同名的类型。

当然,如果您愿意,您可以全力以赴:为新类添加您自己的名称,创建新的运行时和设计时包,添加然后将您的新服务器安装到 IDE VCL Palette 并替换它们你的表格。另一个“正确”的解决方案是分叉 INDY 源,将 DATA 变量添加到非常普通的 TIdCustomTCPServer 类型,然后继续维护您自己的 INDY 分叉分支。

更保守的方法是创建一个 TDictionary< TIdCustomTCPServer,Integer > - http://docwiki.embarcadero.com/CodeExamples/XE4/en/Generics_Collections_TDictionary_(Delphi) 类型的全局变量

然后会变成这样:

procedure TForm1.Button1Click(Sender: TObject);
begin
  GlobalServerDictionary.AddOrSetValue( IdTCPServer1, 12345 ); 
end;

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
var
  ParentServer  : TIdCustomTCPServer;
  MyData        : Integer;
begin
 ParentServer   := TIdServerContext(AContext).Server;
 MyData         := GlobalServerDictionary.Items[ ParentServer ];
end;   

【讨论】:

  • 您发布的第二个代码/方法似乎是个好主意,但我宁愿保留覆盖。我将如何使用TIdCustomTCPServer 做到这一点?
  • Nvm。我实际上不知道我可以像这样将TIdCustomTCPServer 转换为TIdTcpServer。非常感谢您的帮助和回答。
  • @BenjaminWeiss:只有当您确定实例实际上是您将其转换为的类型时,这种“硬”转换才是安全的。否则,您将面临各种可能不会立即浮出水面的麻烦。如果您不确定,并且传递了一个祖先类型的实例,例如aInstance: TAncestor,您最好使用“软”转换:(aInstance as TDescendantOfTAncestor)。当 aInstance 不是 TDescendantOfTAncestor 类型时,这将在运行时引发无效的强制转换异常。
  • @BenjaminWeiss 我的第二个选项与您的消息来源不同(抱歉!看来我昨天在死夜里忽略了它!)只是因为课程被移到单独的 pdule 中,可以重复使用跨越许多不同的形式。如果您只需要一种形式,则该变体与您已经做过的没有区别。再次抱歉。
  • @MarjanVenema +1 - 感谢as 命令的提示。对于答案 - 不要抱歉。多亏了你,我通过将其类型转换为 TIdTCPServer 来管理它以使 Data 属性正常工作。谢谢你:)