Scorpio Wishlist Item
One of the proper jewels of ColdFusion is the dynamic nature of the language. There is nothing I love more than replacing tons of boilerplate code with a few lines of dynamic CF!
One language feature that could be improved is the ability to dynamically call a method on a component. I find CFInvoke a bit unwieldy, syntactically annoying, and in my humble opinion, unnecessary.
Take the following example:
<cfset WhichPreference = "Lunch" />
<cfset WhichStyle = "Heavy">
<cfinvoke component="UserPreferences" method="get#WhichPreference#" returnvariable="LunchForToday">
<cfinvokeargument name="Style" value="#WhichStyle#">
</cfinvoke>
In the above example, we have a UserPreferences object, a variable for the specific class of preferences and an argument.
The intent of the code is to run a method called 'getLunch' on the 'UserPreferences' component and pass 'Heavy' as an argument. (We don't want a simple salad today, boyos!)
We got the job done. Now let us look at a different approach:
<cfset WhichPreference = "Lunch" />
<cfset WhichStyle = "Heavy">
<cfset LunchForToday = UserPreferences['get' & WhichPreference](WhichStyle) />
This code does the exact same thing. The final statement sets LunchForToday equal to UserPreferences.getLunch("Heavy"). To me, this is a lot more intuitive than the cfinvoke method shown above. This code relies on the runtime evaluation of the method and the arguments. Since the 'getLunch' method exists and the call is made at runtime, this is a very logical and valid way to get the job done.
The only problem is it doesn't seem to work. Based on my testing and conversations with Important Folks, this is simply an error in the ColdFusion language parser. I've it on good authority that it has been filed as a bug with the ColdFusion team. I've added it to the Wishlist Wiki for Scorpio and now put it here on this blog.
Does this make sense? Would others find this useful?








<cfset myMethod = "getContacts">
<cfset cfc.salesman = CreateObject("component","includes.salesman")>
<cfset myFunction = cfc.salesman[myMethod]>
It's still more code than there needs to be, but it works great.
myFunction(key,sessionID)
That method works if the function does not rely on any state variables from the component.
For example:
<cfset myFunction = cfc.salesman[myMethod]>
MyFunction in this case points to the Method resolved when 'myMethod' is evaluated. However, if the function is of the form:
<cffunction name="DaFunction" >
<cfreturn variables.instance.someValue
</cffunction>
Then the code will product an error such as:
someValue does not exist in variables.instance.
Thus, the scope and state variables DO NOT come over along with the function.
<cfset cfc._myFunction(key,sessionID)>
(beware of thread safety when do this!)
Thanks for the comment. I want to make sure I understand exactly the thread safety risks. Would this be related solely to a mis-scoped variable, or are there other concerns to watch out for?
DW
Personally, I'd stick to cfinvoke for this use case :)