Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.10.28;
Скачать: 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 вся ветка

Текущий архив: 2007.10.28;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.012 c
15-1190873668
KSergey
2007-09-27 10:14
2007.10.28
Чета политика закрывания веток стала мне не понятной.


1-1186651582
Alex_C
2007-08-09 13:26
2007.10.28
Отловить ошибку в TThread


2-1191585461
Kilkik
2007-10-05 15:57
2007.10.28
Вхождение строки


1-1187177937
partizan
2007-08-15 15:38
2007.10.28
TWebBrowser, текст страници


11-1174745393
SergeR
2007-03-24 17:09
2007.10.28
USE_NAMES и KOLActionList ошибка