1

コールドフュージョン コンポーネントでプロキシ/デリゲート パターンを使用していますが、予期しない結果が得られます (私の見解では)。以下は私のプロキシコンポーネントです - 非常に簡単です。デリゲートしたい実際のコンポーネントで CFC を初期化し、その CFC から名前付き関数をプロキシ関数にマップします (以下はこの例のために簡略化されています)。

次のようにプロキシ コンポーネントを作成しました。

component output="false"{

    /** Constructor for proxy - requires an instance of myFusebox **/
    public MyFuseboxProxy function init( Required any myFb ){
        variables.myFusebox = arguments.myFb;
        return this;
    }

    this.do = variables.proxy;
    this.getApplication = variables.proxy;
    this.getApplicationData = variables.proxy;

    private any function proxy(){    
        var local.functionName = getFunctionCalledName();
        var local.function = variables.myFusebox[local.functionName];
        var local.returnVal = local.function( argumentCollection=arguments );

        return local.returnVal;
    }
}

私のアプリケーションから、次のコードを呼び出します。

    variables.myFusebox = new ab.MyFuseboxProxy( variables.myFusebox );
    variables.myFusebox.getApplicationData().startTime = now();

さて、上記のシナリオでは、プロキシ コンポーネントが getApplicationData() 関数を元の myFusebox コンポーネントに (関数を介して) 直接マップすることを期待しますproxy()

基礎となるコンポーネントのその機能は次のとおりです。

<cffunction name="getApplicationData" returntype="struct" access="public" output="false"
            hint="I am a convenience method to return a reference to the application data cache.">
    <cfreturn getApplication().getApplicationData() />
</cffunction>

そのプロキシはすべて正常に動作しますが、元の myFusebox で上記の関数を使用すると、次のエラーが発生します。

Message: Variable GETAPPLICATION is undefined.
StackTrace: coldfusion.runtime.UndefinedVariableException: Variable GETAPPLICATION is undefined.

そして、thisその関数内で " " をダンプすると、実際にはプロキシ オブジェクトがダンプされます。

誰かがこれまたは私が間違ったことを説明できますか? 関数呼び出しが基になるオブジェクト内にあると、そこから独自のコンテキストが使用されることを期待していました (私のプロキシは、実際にはデリゲートへのパススルーです)。

4

1 に答える 1

1

これがキーポイントだと思います:

関数呼び出しが基になるオブジェクト内にあると、私はそれを期待していました

あなたはこれを持っています:

private any function proxy(){    
    var local.functionName = getFunctionCalledName();
    var local.function = variables.myFusebox[local.functionName];
    var local.returnVal = local.function( argumentCollection=arguments );

    return local.returnVal;
}

このビットを実行すると:

var local.function = variables.myFusebox[local.functionName];

local.functionName によって参照される関数を効果的に引き出して、インスタンスのコンテキスト内で現在のvariables.myFusebox関数に入れてい MyFuseboxProxyます。

したがって、これを行うと:

var local.returnVal = local.function( argumentCollection=arguments );

あなたは実行されていませんがvariables.myFusebox[local.functionName]()(つまり のコンテキストでvariables.myFusebox)、実行されていlocal.function()ます (つまり、プロキシ オブジェクトのコンテキストで)。

ここであなたの論理に従おうとする忍耐力はありませんが、あなたがそのエラーを受け取ることにまだ驚いています. 私はこれが起こると予想していたでしょう:

  1. local.function( getApplicationDatafromへの参照variables.myFusebox) runs getApplication().
  2. getApplication()MyFuseboxProxyインスタンスのコンテキストでは、 はへの参照である必要がありますvariables.proxy()
  3. variables.proxy()プロキシされた関数を として解決しgetApplication()、それを から取り出して、インスタンスvariables.myFuseboxのコンテキストで実行しMyFuseboxProxyます。
  4. getApplication()からの関数のコードが含まれていないvariables.myFuseboxため、次に何が起こるかわかりませんが、これはあなたが望んでいることではありません。

とにかく、重要なのは、内部で関数を実行する代わりに、インスタンスvariables.myFuseboxで実行していることだと思います。MyFuseboxProxyこの種のプロキシを実行したい場合 (そして、これを実行するためにinvoke()特別に用意したものをしばらく無視する場合)、新しいコンテキストで関数を参照するのではなく、元のコンテキストで関数を呼び出す必要があります。

ColdFusion は次の構文を好まないため、このようなごまかしをしていると思います。

someObject[someMethodName]()

という表記にうんざりする[]()。ただし、解決策はこれではありません。

someOutOfContextReference = someObject[someMethodName] 結果 = someOutOfContextReference()

それはこれです:

someObject.someInContextReference = someObject[someMethodName] 結果 = someObject.someInContextReference()

微妙な違いがわかりますか?

ColdFusion 関数は本質的にクロージャではありません。これは、望むように動作するために必要なものです。

于 2013-07-02T21:27:58.177 に答える