Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically call a method from a different component by using cfscript?

I'm looking for the best way to dynamically call a method from a different component in cfscript. Notice that it's concerning a method in a different component. So far I've tried 3 different methods, but none of them seem be exactly what I'm looking for:

All cases are written in cfscript inside a component method. Let's say I'm trying to dynamically call the setName(required string name) method in the MyComponent component. All cases have following variables defined:

var myComp = new MyComponent();
var myMethod = "setName";  
var args = {"name"="foo"};
  • use evaluate() for the job

    evaluate("myComp.#myMethod#(argumentCollection=args)");
    

    pros: is done with very little code
    cons: code is not very 'clean' and use of evaluate() seems to have an 'evil' reputation in the online community. I wouldn't want my code to be evil.

  • use a cfml wrapper for <cfinvoke>

    invoke("MyComponent", myMethod, args);
    

    pros: I can use all functionality of cfinvoke
    cons: It creates a new instance of MyComponent with every invoke.

  • create a dynamicMethod method in MyComponent

    myComp.dynamicMethod(myMethod, args);
    

    dynamicMethod of MyComponent:

    public any function dynamicMethod(required string methodName, required struct argumentColl){  
      var cfcMethod = variables[arguments.methodName];  
      return cfcMethod(argumentCollection=arguments.argumentColl);
    }
    

    pros: I can finally call myComp directly. Most comfortable solution so far.
    cons: I can now call private methods of MyComponent via dynamicMethod.
    (I've also tried the 'function as variable' solution outside of MyComponent, but then the function looses its working context. e.g. if MyComponent would extend a component, the 'super' scope would no longer refer to the extended component).

None of these solutions seem to be perfect, so is there no other way to call a dynamic function from a different controller?
And if there isn't, which one of these is the best solution?

Any advice is welcome, thanks.

like image 246
jan Avatar asked Oct 24 '12 09:10

jan


1 Answers

Good analysis.

One thing you could do here is to more-closely emulate <cfinvoke> with your wrapper function. <cfinvoke> will take either a component path or a component instance (ie: an object) in that COMPONENT attribute. So your 'con' of 'It creates a new instance of MyComponent with every invoke.' isn't really valid.

ColdFusion 10, btw, adds a invoke() function to achieve just this. I note you're on CF9, so this is no help to you. But it's perhaps relevant for other people who might land on this question.

like image 83
Adam Cameron Avatar answered Nov 22 '22 23:11

Adam Cameron