Вниз
Скачать: CL | DM;

Ссылка на метод класса   Найти похожие ветки 

← →
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 вся ветка

Скачать: CL | DM;



Память: 0.47 MB
Время: 0.013 c
15-1190620175
Галинка
2007-09-24 11:49
2007.10.28
Редактировать под Windows, компилировать под Линуксом


1-1187084696
kudatsky
2007-08-14 13:44
2007.10.28
Запуск Winrar с командной строкой


15-1190979232
Megabyte
2007-09-28 15:33
2007.10.28
Компоненты по отправке СМС на моб. тел.


11-1174582796
ElectriC
2007-03-22 19:59
2007.10.28
Collapse


15-1191662383
Kostafey
2007-10-06 13:19
2007.10.28
Динамическое формирование C-строки с несколькими 0




   Наверх