Question

I would like to add a Data Pointer to the TIdTCPServer and I would like to have it also in the TIdCustomTCPServer. I'm not good in overriding, etc. so that's what I have so far:

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.

How could I do this to get the Data Pointer back to any of the OnConnect/OnDisconnect/etc ?

Was it helpful?

Solution

There is no Data property in http://www.indyproject.org/docsite/html/!!MEMBEROVERVIEW_TIdTCPServer.html - are you sure your code compiles and works ?

Well, if there is such a property then just cast the variable back.

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

If there is not - then you have two options. The one is subclassing - adding the property in your class, and second is adding some outside data storage.

Unit IDWithData;
interface uses IdTCPServer;

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

Add this unit at LAST position in the TForm1's unit INTERFACE/USES list and voila! the server now was - invisible to the IDE - replaced with your subclassed one, which have the new Data field, thus the typecast above would work using this new but intentionally same-named type.

Of course, if you wish, you may just go full throttle: add your own name for new class, make new runtime and designtime packages, add then install your new server to IDE VCL Palette and replacing them on all your forms. Another "proper" solution would be forking INDY sources, adding the DATA variable to the very vanilla TIdCustomTCPServer type and then keep maintainging your own forked branch of INDY.

More conservative approach would be just creating a global variable of type TDictionary< TIdCustomTCPServer,Integer > - http://docwiki.embarcadero.com/CodeExamples/XE4/en/Generics_Collections_TDictionary_(Delphi)

Then it would become like this:

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;   
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top