4

如果我有

<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 中我找不到任何方法来做到这一点。

4

5 回答 5

5

Unnamed arguments are passed into a function as a structure with numeric keys matching the positions of the arguments defined in the function arguments. So instead of passing the named arguments, you can convert your array to a struct with numeric keys, and then pass the struct in with argumentCollection:

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

You can easily convert an array to a struct with numeric keys like this:

<cfset args = {}>
<cfloop from="1" to="#arrayLen(arr_arguments)#" index="i">
    <cfset args[i] = arr_arguments[i]>
</cfloop>
于 2013-04-22T16:56:34.010 回答
2

在 Coldfusion 10 中,您可以使用调用函数来执行此操作。按顺序传递参数数组似乎是一种未记录的方式。cfscript 中的示例:

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

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

我在有和没有定义的参数名称的情况下都对此进行了测试,并且保留了参数的顺序。

于 2013-04-23T08:08:29.567 回答
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>

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

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

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

于 2013-04-22T13:47:47.460 回答
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= 一起使用

于 2013-04-22T14:17:26.740 回答
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 的博客上看到的一篇文章,我很确定这也应该在 Adob​​e ColdFusion 中工作。

于 2013-04-22T14:22:14.060 回答