こんにちはすべて:)それは私達がクラスをTRttiMethodしているし、それが機能CreateImplementation()
ウィッヒが動的にそのようプロシージャまたは関数と同じシグネチャを持つとanonimousメソッドを作成することができているのDelphi XE2 RTTIにstackoverflowの時の私の最初の質問:)TypeKind = tkMethodでTRttiTypeのTRttiMethodインスタンスを作成することはできますか?
です体。
TRttiContext.getMethods()
/getMethod()
を使用すると、TRttiMethodのコレクションであるクラスメソッドのコレクションを取得できます。
documentation(http://docwiki.embarcadero.com/VCL/en/RTTI.TRttiMethod)は、TRTTiMethodを直接作成せず、getMethods()を使用してそのインスタンスを取得します。
したがって、TRTTIMethod
インスタンスがある場合、同じシグネチャでメソッドを動的に作成し、後でそれを呼び出すことができます。
質問が...例えば で、我々は... TRttiType
インスタンスオブジェクトウィッヒは= tkMethod
typekindたTRttiContext.getType(typeinfo(TNotifyEvent))
リターンをTNotifyEventを持っています。 TNotifyEventのシグネチャがobjectの手続き(送信者:TObject)であることがわかっています。
これはTRttiMethod
ですか? TRttiMethod.CreateImplementation()
を使用してイベント用のeventHandlerを動的に作成するか、動的にメソッド実装を作成する方法がありますか?
PS:イベントチェーンのようなものを作成することです。コンパイル時にはイベントタイプ/シグネチャがわからないので、ジェネリックをTEvenChainのように使うことができます<TNotifyEvent>。 Chainは登録されたイベントハンドラのコレクションを持っているので、コンパイル時にハンドラの型がわからないため、動的にハンドラの型を作成しなければならず、そのハンドラはパラメータを取得してハンドラを呼び出すだけです。
更新:ここで は、いくつかのコードは、(アイデアは、イベントハンドラチェーンを作成することである)である。
procedure TMainForm.FormCreate(Sender: TObject);
begin
FEventChain := TNotifyChain.Create();
FEventChain.AddHandler(event1);
FEventChain.AddHandler(event2);
TestButton.OnClick := FEventChain.EventHandler;
end;
Event1
& event2
は方法形式の(sender : TObject)
あります。 は、それが一般的な例ではありません(T、この場合にNotifyEventから/ TChain <TNotifyEvent>である) TEventChain.EventHandler
がTNotifyEvent
すぎる
TNotifyChain
は
TNotifyChain = class(TObject)
strict private
FEvent : TNotifyEvent;
FItems : TList<TNotifyEvent>;
FCtx : TRttiContext;
public
procedure TestNotifyHandler(sender : TObject); virtual; abstract;
constructor Create();
procedure AddHandler(eh : TNotifyEvent);
property EventHandler : TNotifyEvent read FEvent;
end;
EventHandler
性がFEvent
変数にマッピングされています。そして、FEvent
は、イベント/ハンドラのタイプが不明であると仮定して割り当てられていません。
ので、コンストラクタで、我々はTNotifyEvent
署名で仮想メソッドを作成し、FEvent
にそのコードを割り当てます。ここ
constructor TNotifyChain.Create();
var st: TRttiType;
//et : TRttiMethodType;
Callback : TMethodImplementationCallback;
rttiMethod : TRttiMethod;
m : TMethod;
mi : TMethodImplementation;
begin
inherited;
FItems := TList<TNotifyEvent>.Create();
FCtx := TRttiContext.Create();
//et := FCtx.GetType(typeinfo(TNotifyEvent)) as TRttiMethodType;
st := FCtx.GetType(self.ClassType);
rttiMethod := st.GetMethod('TestNotifyHandler');
Callback := procedure(UserData: Pointer;
const Args: TArray<TValue>;
out Result: TValue)
var i : integer;
e : TMethod;
begin
for i := 0 to FItems.Count - 1 do begin
e := TMethod(Fitems[i]);
result := Invoke(e.Code, args, rttiMethod.CallingConvention, nil);
end;
end;
mi := rttiMethod.CreateImplementation(self, Callback);
m.data := self;
m.Code := mi.CodeAddress;
FEvent := TNotifyEvent(m);
end;
私は、私が思うTRttimethod.CreateImplementation()
を使用して、同じシグネチャを持つ実際のハンドラを作成するために、TestNotifyHandler
メソッドを使用します実際に使用されている実際のイベント(一般的な場合)の型/カウントと呼び出し規約に関する情報を持っているので、TRttiMethodType
からTNotifyEvent
を使用して実行時のイベントハンドラの実装を作成する方法があります。
今までにどれくらい取得しましたか、分けてください。 – menjaraz
@menjaraz私はこの問題を解決していません。私にとっては「楽しい」ための「本当の」仕事ではありませんでした。私は私のブログでこれについての記事を書いています:http://teran.karelia.pro/articles/item_4508.html(でもそれはもともとロシア語で書かれています)。 Googleを使用して英語に翻訳することができます[link] http://translate.google.com/translate?sl=ru&tl=ja&js=n&prev=_t&hl=ru&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F% 2Fteran.karelia.pro%2Farticles%2Fitem_4508.html&act = url – teran
ありがとうございます。 – menjaraz