Reputation: 10043
I am using a proxy/delegate pattern in a coldfusion component, and am getting unexpected results (from my point of view). Below is my proxy component - its pretty straight forward, I just init the CFC with the actual component I want to delegate to, and then map the named functions from that CFC through to a proxy function (the below is simplified for this example)
I have created a proxy component as follows:
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;
}
}
From my application I call the following code:
variables.myFusebox = new ab.MyFuseboxProxy( variables.myFusebox );
variables.myFusebox.getApplicationData().startTime = now();
Now, in the above scenario, I would expect my proxy component to map the getApplicationData() function straight through to the original myFusebox component (via my proxy()
function).
That function in the underlying component is as follows:
<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>
That proxy all works fine, however, once I am in the above function in the original myFusebox I get the following error:
Message: Variable GETAPPLICATION is undefined.
StackTrace: coldfusion.runtime.UndefinedVariableException: Variable GETAPPLICATION is undefined.
And if I dump "this
" inside that function, it actually dumps my proxy object.
Can anyone explain this or what I have done wrong? I was expecting that once the function call was inside the underlying object, it would just use its own context from there (my proxy just being a pass through really to the delegate)
Upvotes: 1
Views: 280
Reputation: 29870
I think this is the key point:
I was expecting that once the function call was inside the underlying object
You've got this:
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;
}
When you do this bit:
var local.function = variables.myFusebox[local.functionName];
you are effectively pulling the function referenced by local.functionName
out of variables.myFusebox
, and putting it into the current function, within the context of your MyFuseboxProxy
instance.
So when you do this:
var local.returnVal = local.function( argumentCollection=arguments );
You are not running variables.myFusebox[local.functionName]()
(so in the context of variables.myFusebox
), but you are running local.function()
(so in the context of your proxy object).
I don't have the patience to try to follow your logic here, but I am still surprised you get that error. I would have expected this to happen:
local.function
(a reference to getApplicationData
from variables.myFusebox
) runs getApplication()
.getApplication()
in the context of the MyFuseboxProxy
instance should be a reference to variables.proxy()
.variables.proxy()
resolves the proxied function as getApplication()
, and pulls that out of variables.myFusebox
, and runs it in the context of your MyFuseboxProxy
instance.getApplication()
function from variables.myFusebox
, so I dunno what would happen next, but this is not what you want to be happening.Anyway, the crux is - I think - that instead of running the functions inside variables.myFusebox
, you're running them in your MyFuseboxProxy
instance instead. If you want to do this sort of proxying (and ignoring for a moment you have invoke()
specifically for doing this), you need to still call the function in its original context, not reference it in some new context.
I guess you're doing all this horsing around because ColdFusion doesn't like this syntax:
someObject[someMethodName]()
It baulks at the []()
notation. However the solution is not this:
someOutOfContextReference = someObject[someMethodName] result = someOutOfContextReference()
It's this:
someObject.someInContextReference = someObject[someMethodName] result = someObject.someInContextReference()
See the subtle difference?
ColdFusion functions are not intrinsically closures, which is what you'd need them to be to work the way you want.
Upvotes: 1