使用动态参数数组调用函数

时间:2013-04-22 12:09:46

标签: coldfusion cfml openbd

如果我有

<cfset arr_arguments = ["a","b","c"]>
<cfunction name="someFunction">
 <cfargument name="someArgumentOne">
 <cfargument name="someArgumentTwo">
 <cfargument name="someArgumentThree">

</cffunction>

有没有办法使用someFunction参数调用arr_arguments,类似于someFunction("a","b","c")?我当然知道我可以使用argumentCollection将(键控)结构传递给函数,但我特别询问传入(无键)数组。在JS中,可以使用someFunction.apply(this,arr_arguments)轻松完成,但在coldfusion中,我无法找到任何方法。

5 个答案:

答案 0 :(得分:4)

未命名的参数作为结构传递给函数,其数字键与函数参数中定义的参数的位置相匹配。因此,您可以将数组转换为带有数字键的结构,然后使用argumentCollection传递结构,而不是传递命名参数:

<cfset arr_arguments = {"1"="a","2"="b","3"="c"}>
<cfset someFunction(argumentCollection=arr_arguments)>

您可以使用如下数字键轻松地将数组转换为结构:

<cfset args = {}>
<cfloop from="1" to="#arrayLen(arr_arguments)#" index="i">
    <cfset args[i] = arr_arguments[i]>
</cfloop>

答案 1 :(得分:2)

在Coldfusion 10中,您可以使用invoke function来执行此操作。它似乎是一种无法按顺序传递参数数组的方法。 cfscript中的示例:

invoke('', 'someFunction', ['a','b','c']);

invoke的第一个参数是组件名称(或UDF的空字符串)。第二个是函数名,第三个是参数数组。请注意,组件和函数名称必须作为字符串传递。

我测试了这个有和没有定义的参数名称,并保留了参数的顺序。

答案 2 :(得分:1)

好的,如果你想调用带有任意参数数组的函数,我建议的最佳选择就是创建一个包装函数。见下面的示例代码

<cfscript>
    function testMe(
        required string arg1,
        required string arg2
    ) {
        writedump(arguments);
    }

    function invokeFunction(
        required inFunction,
        required array functionArguments
    ) {
        var stcArguments = {};
        // Introspect to get the method parameters
        var arrFunctionArguments = GetMetaData(arguments.inFunction).parameters;
        // Now figure out what we are iterating to
        var numArgumentsToParse = Min(ArrayLen(arguments.functionArguments),ArrayLen(arrFunctionArguments));
        // Populate the arguments structure
        for (var i=1;i<=numArgumentsToParse;i++) {
            stcArguments[arrFunctionArguments[i].name] = arguments.functionArguments[i];
        }
        // And try to call it
        return arguments.inFunction(
            argumentCollection = stcArguments
        );
    }

    invokeFunction(testMe,[1,2]);           // Works fine
    invokeFunction(testMe,[1,2,3,4]);       // Just skips 3 and 4
//  invokeFunction(testMe,[1]);             // Errors due to not enough arguments
//  invokeFunction(fakeFunctionName,[1]);   // Errors due to undefined function
</cfscript>

如果发生以下任何一种情况,这当然会出错

  • 一个或多个参数的类型不正确
  • 该功能实际上并不存在
  • 并非所有必需参数都在
  • 中传递

但你可以在外面处理。这将使用内省来计算参数名称,相应地填充结构,并调用所请求的函数。

答案 3 :(得分:1)

这是一个UDF,它将为您做到这一点:

<cfscript>
function test_function(a,b,c){      
    writeOutput("arguments.a"&arguments.a&"<br>");
    writeOutput("arguments.b"&arguments.b&"<br>");
    writeOutput("arguments.c"&arguments.c&"<br>");

    return arguments.a & "::" & arguments.b & "::" & arguments.c;
}

function invoke_positional(func,arr){
    var metaData = GetMetaData(func);
    var args={};
    for(var pos=1;pos<=ArrayLen(arr);pos++){
        args[metaData.parameters[pos].name]=arr[pos];
    }
    return arguments.func(argumentCollection=args);
}

data = ["StringOne","StringTwo",22];

result = invoke_positional(test_function,data);

</cfscript>

<cfoutput>
<p>
Returned: #result#
</p>
</cfoutput>

invoke_positional通过使用UDF的元数据来构建一组命名参数,然后将它们与argumentCollection =

一起使用

答案 4 :(得分:0)

因此,我发现有一个选项是与实际的实参数范围分开创建一个参数对象,只需使用数字索引将值添加到它。

<cfset args_input = createObject("java","com.naryx.tagfusion.cfm.engine.cfArgStructData").init()>
<cfloop from="1" to="#arraylen(arr_arguments)#" index="i">
    <cfset args_input[i] = arr_arguments[i]>
</cfloop>
<cfset someFunction(argumentCollection=args_input)>

如果您使用adobe coldfusion遇到这种情况,我会建议您尝试

<cfset correctClass = arguments.getClass().getName()>

要将字符串传递给createObject。或者,如果这不起作用,只需要一个专用函数来返回一个空参数对象

<cfset args_input = this.generateArgumentObject()>

<cffunction name="generateArgumentObject">
    <cfreturn arguments>
</cffunction>

哦,我确切知道的是,它肯定会在OpenBD中运行,并且基于我过去在Ben Nadel的博客上看到的帖子,我很确定这也应该适用于Adobe ColdFusion。