![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
|
|
#1
|
||||
|
||||
|
Всем привет!
На досуге работаю над чем-то вроде движка, который позволяет посредством интерфейса командной строки управлять внутренностями программы. Например, есть возможность прописать в консоли что-то типа "Form1.Button1.Left:=Form1.Button1.Left - 10", и указанный объект (Button1) будет смещен на 10 пикселей влево, хвала механизму RTTI и несложному самодельному интерпретатору команд. Однако, продвижение в работе застопорилось, как только я решил добавить возможность переприсваивать значения не только полей, но и методов (скажем, чтобы поддерживались и работали также команды вида "Form1.Button1.OnClick:=Form1.Button2.OnClick" ). Оказалось, решение проблемы неинтуитивно. Можно, конечно, сделать примитивно: Код:
TargetObject: TControl;
MethodName: string;
NewMethodAddress: Pointer;
{...}
MethodName:=UpperCase(MethodName);
if MethodName = 'ONCLICK' then
@TargetObject.OnClick:=@NewMethodAddress
else
if MethodName = 'ONMOUSEDOWN' then
@TargetObject.OnMouseDown:=@NewMethodAddress
else
{... и так далее, список на несколько экранов, плюс способности Ванги угадывать, какие вообще методы есть в данном классе ...}Но мне на такой код даже смотреть больно ![]() Итак, вопрос такой: есть ли более элегантный способ "заменить" нужный метод в рантайме? Какая-то магическая функция SetMethodAddress? |
|
#2
|
|||
|
|||
|
Да, вроде, как бы обработчик события тоже свойство, просто специальное, и должно быть доступно через RTTI...
Вот примерная идея (там в последней строчке вываливается Invalid TypeCast, надо разбираться): Код:
uses System.Rtti;
procedure TForm1.SetEvent(Obj : String; Evt : String; Mth : String);
var
ctx : TRTTIContext;
rtype : TRTTIType;
rmethod : TRTTIMethod;
rprop : TRttiProperty;
m : Pointer;
mm : TMethod;
o : TComponent;
begin
ctx := TRTTIContext.Create;
Try
rtype := ctx.GetType(Self.ClassType);
rmethod := rtype.GetMethod(Mth);
m := rmethod.CodeAddress;
mm.Code := m;
o := Self.FindComponent(Obj);
rtype := ctx.GetType(o.ClassType);
rprop := rtype.GetProperty(Evt);
rprop.SetValue(o,TValue.From(mm));
Finally
ctx.Free;
End;
end;PS. Не работает для приватных методов (проверено). Для них просто RTTI не генерится, надо что бы был папблик. |
| Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
Lothlorien (01.02.2020)
| ||
|
#3
|
||||
|
||||
|
Видимо, я не до конца простудировал RTTI. Спасибо, буду копать в этом направлении.
Да, приватные методы оно не видит, по крайней мере на Delphi 7 RTTI оперирует только с published элементами класса |