Форум: "Основная";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];
ВнизСсылка на метод класса Найти похожие ветки
← →
Debug © (2007-08-11 09:46) [0]Необходимо реализовать вызов метода класса по строковой команде. Проблема в том, что вызов метода происходит от объекта nil, а не от вызывающего.
type
TCommandHandler = procedure (I: Integer) of object;
TCommandManager = class (TObject)
protected
procedure SetCommandHandler(Command: string; Handler: TCommandHandler);
procedure DoCommand1(I: Integer);
procedure DoCommand2(I: Integer);
...
public
procedure ProcessCommand(Command: string);
end;
procedure TCommandManager.SetCommandHandler(Command: string; Handler: TCommandHandler);
begin
SomeStringIndexedArray[Command] := Handler;
end;
procedure TCommandManager.ProcessCommand(Command: string; I: Integer);
var
Handler: TCommandHandler;
begin
@Handler := Pointer(SomeStringIndexedArray[Command]);
if Assigned(Handler) then
Handler(I);
end;
procedure TCommandManager.DoCommand1(I: Integer);
begin
// Здесь при вызове метода Self = nil!
end;
Подскажите, возможно ли организовать обработку комманд таким способом? Или каким-нибудь другим, но кроме кейса и кроме выделения каждой команды в отдельный класс.
← →
Lacmus © (2007-08-11 10:00) [1]Ошибка здесь
Handler := SomeStringIndexedArray[Command];
← →
MetalFan © (2007-08-11 10:28) [2]
> SomeStringIndexedArray
это еще что за зверь????
нельзя в делфи использовать строку для индексации массива... только если свойство-массив
← →
Debug © (2007-08-11 10:50) [3]2Lacmus: в чем ошибка?
2MetalFan: это и есть свойство массив TObject"ов
← →
Lacmus © (2007-08-11 11:04) [4]>Debug © (11.08.07 10:50) [3]
TCommandHandler -
TMethod = record
Code, Data: Pointer;
end;
← →
Юрий Зотов © (2007-08-11 12:12) [5]Отдельный менеджер команд плодить не стал, а сделал им саму форму. Сути это не меняет.
unit Unit6;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TCommandHandler = procedure(I: Integer) of object;
TForm1 = class(TForm)
ListBox1: TListBox;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
protected
procedure SetCommandHandler(Command: string; Handler: TCommandHandler);
procedure DoCommand1(I: Integer);
procedure DoCommand2(I: Integer);
public
procedure ProcessCommand(Command: string; Sender: TObject; Param: Integer);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.DoCommand1(I: Integer);
begin
ShowMessage(Format("DoCommand1: Self = %s, Parameter = %d", [TComponent(Self).Name, I]))
end;
procedure TForm1.DoCommand2(I: Integer);
begin
ShowMessage(Format("DoCommand2: Self = %s, Parameter = %d", [TComponent(Self).Name, I]))
end;
procedure TForm1.ProcessCommand(Command: string; Sender: TObject; Param: Integer);
var
Index: integer;
Method: TMethod;
begin
Index := ListBox1.Items.IndexOf(Command);
if Index < 0 then
raise Exception.CreateFmt("Unknown command "%s"", [Command]);
Method.Code := ListBox1.Items.Objects[Index];
Method.Data := Sender;
TCommandHandler(Method)(Param)
end;
procedure TForm1.SetCommandHandler(Command: string; Handler: TCommandHandler);
begin
ListBox1.Items.AddObject(Command, TObject(TMethod(Handler).Code))
end;
// ========================================
procedure TForm1.FormCreate(Sender: TObject);
begin
SetCommandHandler("Command1", DoCommand1);
SetCommandHandler("Command2", DoCommand2);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Index: integer;
Obj: TObject;
begin
Index := ListBox1.ItemIndex;
if Index < 0 then
raise Exception.Create("Command not selected");
if Index = 0 then
Obj := Self
else
Obj := Sender;
ProcessCommand(ListBox1.Items[Index], Obj, Index)
end;
end.
Но лучше не корежить Self, а вввести параметр Sender:
type
TCommandHandler = procedure(Sender: TObject; I: Integer) of object;
Тогда в ProcessCommand нужно будет изменить 2 строчки:
Method.Data := Self;
TCommandHandler(Method)(Sender, Param)
Соответственно изменятся заголовки всех DoCommandX.
Что получим: Self, как ему и положено, будет указывать на менеджер команд, а Sender - на объект, инициировавший выполнение команды.
← →
Юрий Зотов © (2007-08-11 12:16) [6]Вдогонку: команды хранятся в ListBox"е лишь потому, что для демонстрашки это было удобнее. В реальном коде, видимо, удобнее будет TStringList.
← →
Leonid Troyanovsky © (2007-08-11 12:40) [7]
> Debug © (11.08.07 09:46)
> Необходимо реализовать вызов метода класса по строковой
> команде.
http://www.rsdn.ru/Forum/Message.aspx?mid=476748&only=1
Гм.. Кто здесь еще искал процедуру по имени.
--
Regards, LVT.
← →
Debug © (2007-08-11 14:26) [8]Огромное спасибо!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.044 c