2012-02-17 5 views
7

こんにちはすべて:)それは私達がクラスを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.EventHandlerTNotifyEventすぎる

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を使用して実行時のイベントハンドラの実装を作成する方法があります。

+0

今までにどれくらい取得しましたか、分けてください。 – menjaraz

+0

@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

+0

ありがとうございます。 – menjaraz

答えて

4

TRttiTypeとタイプキンドTkMethodは、TRttiMethodTypeと表示されます。メソッドではないので、TRttiMethodを取得することはできません。メソッドポインタですが、TRttiMethodTypeとそのInvokeメソッドを見れば、必要なものを正確に見つけることができます。

+0

お返事ありがとうございます。 私は 'TRttiMethodType.Invoke'が私に必要なものであるとは思わない。実際に存在するオブジェクトのメソッドを呼び出すために使用されるためです。私の場合、そのような方法はありません。私は前もってそれを作成しなければなりません。 問題を示すために私の 'TNotifyChain'クラスのソースを追加しました。 – teran

関連する問題