Delphi 将对象方法添加到stringlist,以便可以按名称调用它们
我有一个服务器代码,它接受来自客户端的命令并执行由接收到的命令确定的对象方法。我想使用AddObject构建一个stringlist,将命令与所需的过程相关联。这在独立过程中可以正常工作,但在尝试将对象方法添加到stringlist时会出现“variable required”错误。下面是示例代码:Delphi 将对象方法添加到stringlist,以便可以按名称调用它们,delphi,Delphi,我有一个服务器代码,它接受来自客户端的命令并执行由接收到的命令确定的对象方法。我想使用AddObject构建一个stringlist,将命令与所需的过程相关联。这在独立过程中可以正常工作,但在尝试将对象方法添加到stringlist时会出现“variable required”错误。下面是示例代码: type TExample = class public var Commands: TStringList; constructor Create; destruc
type
TExample = class
public
var Commands: TStringList;
constructor Create;
destructor Destroy; override;
procedure ExecCommand(Cmd, Msg: string);
procedure Alpha(Msg: string);
procedure Beta(Msg: string);
procedure Gamma(Msg: string);
end;
constructor TExample.Create;
begin
inherited Create;
Commands := TStringList.Create;
Commands.AddObject('Alpha', @Alpha); // fails to compile: "variable required"
Commands.AddObject('Beta', @Beta);
Commands.AddObject('Gamma', @Gamma);
end;
destructor TExample.Destroy;
begin
Commands.Free;
inherited Destroy;
end;
procedure TExample.ExecCommand(Cmd, Msg: string);
type
TProcType = procedure(Msg: string);
var
i: integer;
P: TProcType;
begin
i := Commands.IndexOf(Cmd);
if i >= 0 then
begin
P := TProcType(Commands.Objects[i]);
P(Msg);
end;
end;
procedure TExample.Alpha(Msg: string);
begin
ShowMessage('Alpha: ' + Msg);
end;
procedure TExample.Beta(Msg: string);
begin
ShowMessage('Beta: ' + Msg);
end;
procedure TExample.Gamma(Msg: string);
begin
ShowMessage('Gamma: ' + Msg);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Example: TExample;
Cmd, Msg: string;
begin
Cmd := Edit1.Text;
Msg := Edit2.Text;
Example := TExample.Create;
Example.ExecCommand(Cmd, Msg);
Example.Free;
end;
您试图对
TExample
对象调用非静态类方法,因此需要将of object
添加到TPropType
的声明中,以处理Self
参数:
类型
TProcType=对象的过程(消息:字符串);
但是,非静态对象方法指针比普通指针大,因为它们携带两条信息—一条指向对象的指针,一条指向调用对象的方法的指针—因此不能直接将非静态方法指针存储在TStringList.Objects[]
列表中。但是,您可以间接存储它
一种方法是动态分配方法指针,例如:
类型
TExample=class
公众的
var命令:TStringList;
构造函数创建;
毁灭者毁灭;推翻
过程执行命令(Cmd,Msg:string);
程序Alpha(Msg:string);
程序Beta(Msg:string);
程序伽马(消息:字符串);
结束;
类型
TProcType=对象的过程(消息:字符串);
PProcType=^TProcType;
构造函数TExample.Create;
变量
P:PProcType;
开始
继承创造;
命令:=TStringList.Create;
新的(P);
P^:=@Alpha;
AddObject('Alpha',TObject(P));
新的(P);
P^:=@Beta;
AddObject('Beta',TObject(P));
新的(P);
P^:=@伽马;
AddObject('Gamma',TObject(P));
结束;
析构函数TExample.Destroy;
变量
I:整数;
开始
对于I:=0到Commands.Count-1 do
Dispose(pprotype(Commands.Objects[I]);
命令。免费;
继承性破坏;
结束;
过程TExample.ExecCommand(Cmd,Msg:string);
变量
i:整数;
P:PProcType;
开始
i:=Commands.IndexOf(Cmd);
如果i>=0,则
开始
P:=pprotype(Commands.Objects[i]);
P^(味精);
结束;
结束;
过程TExample.Alpha(消息:字符串);
开始
ShowMessage('Alpha:'+Msg);
结束;
程序TExample.Beta(消息:字符串);
开始
ShowMessage('Beta:'+Msg);
结束;
程序TExample.Gamma(消息:字符串);
开始
ShowMessage('Gamma:'+Msg);
结束;
程序TForm1.按钮1单击(发送方:TObject);
变量
示例:TExample;
Cmd,Msg:string;
开始
Cmd:=Edit1.Text;
Msg:=Edit2.Text;
示例:=TExample.Create;
ExecCommand(Cmd,Msg);
例如,免费;
结束;
另一种方法是存储指向类方法的静态指针,然后在需要调用方法时使用记录来帮助您,如注释中描述的@OndrejKelle,例如:
类型
TExample=class
公众的
var命令:TStringList;
构造函数创建;
毁灭者毁灭;推翻
过程执行命令(Cmd,Msg:string);
程序Alpha(Msg:string);
程序Beta(Msg:string);
程序伽马(消息:字符串);
结束;
类型
TProcType=对象的过程(消息:字符串);
构造函数TExample.Create;
开始
继承创造;
命令:=TStringList.Create;
Commands.AddObject('Alpha',TObject(@TExample.Alpha));
Commands.AddObject('Beta',TObject(@TExample.Beta));
Commands.AddObject('Gamma',TObject(@TExample.Gamma));
结束;
析构函数TExample.Destroy;
开始
命令。免费;
继承性破坏;
结束;
过程TExample.ExecCommand(Cmd,Msg:string);
变量
i:整数;
P:TProcType;
开始
i:=Commands.IndexOf(Cmd);
如果i>=0,则
开始
t方法(P)。数据:=自身;
TMethod(P).Code:=指针(Commands.Objects[i]);
P(味精);
结束;
结束;
过程TExample.Alpha(消息:字符串);
开始
ShowMessage('Alpha:'+Msg);
结束;
程序TExample.Beta(消息:字符串);
开始
ShowMessage('Beta:'+Msg);
结束;
程序TExample.Gamma(消息:字符串);
开始
ShowMessage('Gamma:'+Msg);
结束;
程序TForm1.按钮1单击(发送方:TObject);
变量
示例:TExample;
Cmd,Msg:string;
开始
Cmd:=Edit1.Text;
Msg:=Edit2.Text;
示例:=TExample.Create;
ExecCommand(Cmd,Msg);
例如,免费;
结束;
但是不管怎样,一个TStringList
都不是这个工作的最佳工具。你真的应该改用a,这样你就不必跳过不必要的圈,例如:
使用
…,System.Generics.Collections;
类型
TProcType=对象的过程(消息:字符串);
TExample=class
公众的
var命令:TDictionary;
构造函数创建;
毁灭者毁灭;推翻
过程执行命令(Cmd,Msg:string);
程序Alpha(Msg:string);
程序Beta(Msg:string);
程序伽马(消息:字符串);
结束;
构造函数TExample.Create;
开始
继承创造;
命令:=TDictionary.Create;
Commands.Add('Alpha',@Alpha);
添加('Beta',@Beta);
Add('Gamma',@Gamma);
结束;
析构函数TExample.Destroy;
开始
命令。免费;
继承性破坏;
结束;
过程TExample.ExecCommand(Cmd,Msg:string);
变量
P:TProcType;
开始
如果命令.TryGetValue(Cmd,P),则
P(味精);
结束;
过程TExample.Alpha(消息:字符串);
开始
ShowMessage('Alpha:'+Msg);
结束;
程序TExample.Beta(消息:字符串);
开始
ShowMessage('Beta:'+Msg);
结束;
程序TExample.Gamma(消息:字符串);
开始
ShowMessage('Gamma:'+Msg);
结束;
程序TForm1.按钮1单击(发送方:TObject);
变量
示例:TExample;
Cmd,Msg:string;
开始
Cmd:=Edit1.Text;
Msg:=Edit2.Text;
示例:=TExample.Create;
ExecCommand(Cmd,Msg);
例如,免费;
结束;
您试图对TExample
对象调用非静态类方法,因此需要将of object
添加到TPropType
的声明中,以处理Self
参数:
类型
TProcType=过程(消息:字符串)
type
TExample = class
published
procedure Alpha(Msg: string);
procedure Beta(Msg: string);
procedure Gamma(Msg: string);
public
procedure ExecCommand(Cmd, Msg: string);
end;
procedure TExample.ExecCommand(Cmd, Msg: string);
type
TProcType = procedure(Msg: string) of object;
var
M: TMethod;
P: TProcType;
begin
M.Code := Self.MethodAddress(Cmd);
if M.Code = Nil then ShowMessage('Unknown command: ' + Cmd) else
begin
M.Data := Pointer(Self);
P := TProcType(M);
P(Msg);
end;
end;