2016-11-02 8 views
1

私は次のような状況に陥ります。Delphi組み込みコールバック関数

1つのコンポーネントを作成しました。私は1つのメソッドを使用するとき、コンポーネントからいくつかのフィードバックを得たいと思います。

同様のcomponent.Method(param1:コールバック関数);

これまでにすべて良好で光沢があります。

プロジェクトのユニットは次のとおりです。

form主な目に見える形。

dataModule - コンポーネントを操作しています。

フォームは、フィードバックを受け取るためにデータモジュールに1つのコールバック関数を渡す必要があります。このコールバック関数は、コンポーネントとは異なる関数です(より多くのパラメータを持ちます)。

私はこれを行う方法を知らない。

TFeedBackProcedure = procedure(param1 : Integer) of object; 
TFeedBackProcedureByTypeOf = procedure(aTypeOf : Integer; param1 : Integer) of object; 

// component 
procedure Syncro(feedBack : TFeedBackProcedure); 
begin 
    //somewhere inside 
    for i := 0 to 15 do begin 
    feedBack(i); 
    end; 
end; 
// the feeedback received so far when someone use the Syncro procedure is the value of i 

// the datamodule 
// inside of a method I need to pass also the i received from compoent also a typeof value used only inside datamodule 
procedure UseMethod(feedbackProcedure : TFeedBackProcedureByTypeOf); // the extended callback 
begin 
    typeof = 1; 
    if component.Syncro(???) then begin // <-------- how to ??? 
    // do stuff 
    end; 
end; 

// the main form 
// the real callback function 
procedure TFormMain.Feddback(aTypeOf : Integer; param1: Integer); 
begin 
    if aTypeOf = 0 then begin 
    label1.caption = IntToStr(param1); 
    end else begin 
    label2.caption = IntToStr(param1); 
    end; 
end; 
// usage of datamodule 
procedure TFormMain.btn1Click(Sender: TObject); 
begin 
    dataModule.UseMethod(Feddback); 
end; 

これを行うための他の方法?一番簡単な方法は、また、それようTFeedbackProcedureの型宣言を変更することがありますが、コンポーネントを自分で書いた場合

TKSのたくさん

はRazvan

答えて

2

(私もFMXの環境には、これを必要とします)匿名メソッド(だけでなく、オブジェクトのメソッドを)受け入れる:

TFeedBackProcedure = reference to procedure(param1 : Integer); 

これは、あなたが代わりに拡張メソッドをラップし、そのようにそれを呼び出すことができます:

procedure UseMethod(feedbackProcedure : TFeedBackProcedureByTypeOf); 
var 
    _typeOf : integer; 
begin 
    _typeOf = 1; 
    component.Syncro(procedure(AParam : integer) 
        begin 
        feedbackProcedure(_typeOf, AParam); 
        end); 
end; 

例では、実際に単純な手続きとして宣言したときにブール値を返す関数であるかのように.Synchroを書いているので、ここではメソッドを呼び出すことを示しただけです。代替案として


あなたがメソッドのシグネチャを変更したり、既存のクラスにラッパーを追加することができない場合、あなたは常に仕事をするためのラッパークラスを書くことができます。ここでは専用のラッパークラスを示しましたが、これらのフィールドとメソッドを任意の適切なクラスに簡単に追加して、機能を正しいシグネチャーのオブジェクトメソッドにラップすることもできます。実装と

TCallbackContainer = class 
    private 
     FParam : integer; 
     FFeedbackProcByTypeOf : TFeedBackProcedureByTypeOf; 
    public 
     constructor Create(AProcByTypeOf : TFeedBackProcedureByTypeOf); 
     procedure WrapCallback(AParam:integer); 
     property IntParam : integer read FParam write FParam; 
    end; 

constructor TCallbackContainer.Create(AProcByTypeOf : TFeedBackProcedureByTypeOf); 
    begin 
    FFeedbackProcByTypeOf := AProcByTypeOf; 
    end; 

    procedure TCallbackContainer.WrapCallback(AParam: Integer); 
    begin 
    FFeedbackProcByTypeOf(FParam, AParam); 
    end; 

あなたはその後、呼び出すことができます。このように:参照がカウントされ、匿名メソッドとは異なり、あなたはここでLCallbackContainerオブジェクトの有効期間を管理する必要が

procedure UseMethod(feedbackProcedure : TFeedBackProcedureByTypeOf); 
var 
    LCallbackContainer : TCallbackContainer; 
begin 
    LCallBackContainer := TCallbackContainer.Create(feedbackProcedure); 
    try 
    LCallBackContainer.IntParam := 1; 
    component.Syncro(LCallbackContainer.WrapCallback); 
    finally 
    LCallBackContainer.Free; 
    end; 
    { Or, make it FCallBackContainer and manage lifetime somehow...} 
end; 

どういうわけか。 .Synchroが実際には完全に同期していて、返されたときにコールバックコンテナを解放することができれば、これはローカルとして表示されています。もし。しかし、実際には非同期メソッドであり、作業が完了する前に戻り、コールバックラッパーのライフタイムを管理する方法が必要になります。あなたはまた、その名前の the standard methodを非表示になります。このため、変数 TypeOfを付けないようにする必要があり


System.TypeOfは推奨されていませんが、このような名前の競合を回避することは、依然として有効です。

関連する問題