3

在 ColdFusion 8 之前的版本中,如果结构中有任何组件,则重复函数会引发错误。在 8 及更高版本中它可以工作,但是在复制组件时会出现问题。

所以,我需要的是一种创建忽略组件的结构的深层副本的方法。出于我的调试目的,我需要代码中特定点的变量范围的快照,因此效率并不重要,因为它永远不会脱离开发环境。目前使用 CF 7,如果只是为了解决这个直接的问题,我会接受 8 的报价,但我不控制升级:(

4

2 回答 2

5

当你正在杀死脑细胞时,我尝试了一个递归函数;)它不包括组件和 java/com 对象。哪个 MX7 都不能复制。我将函数放入组件中以避免篡改variables范围。然后将实例存储在request作用域中。

它没有经过严格的测试。所以我确信还有改进的余地。

用法

<cfset request.util = createObject("component", "Util")>
<cfset request.copy = request.util.duplicateStructMinusObjects(variables)>
<cfdump var="#request.copy#">

实用程序.cfc

<cfcomponent>
    <cfscript>
            function duplicateArrayMinusObjects(input) {
                    var x      = "";
                    var value  = "";
                    var output = arrayNew(1);

                    for (x = 1; x lte arrayLen(arguments.input); x = x + 1) {
                            value = arguments.input[x];

                            // note components are considered structures
                            if (IsStruct(value) and not IsObject(value)) {
                                    arrayAppend(output, duplicateStructMinusObjects(value));
                            }
                            else if (IsArray(value)) {
                                    arrayAppend(output, duplicateArrayMinusObjects(value));                
                            }
                            else if (not IsObject(value)){        
                                    arrayAppend(output, duplicate(value));
                            }
                    }        
                    return output;
            }

            function duplicateStructMinusObjects(input) {
                    var key    = "";
                    var value  = "";
                    var output = structNew();

                    for (key in arguments.input) {
                            value = arguments.input[key];

                            // note components are considered structures
                            if (IsStruct(value) and not IsObject(value)) {
                                    output[key] = duplicateStructMinusObjects(value);
                            }
                            else if (IsArray(value)) {
                                    output[key] = duplicateArrayMinusObjects(value);
                            }
                            else if (not IsObject(value)){        
                                    output[key] = duplicate(value);
                            }
                    }

                    return output;
            }
    </cfscript>
</cfcomponent> 
于 2011-09-17T08:30:36.970 回答
1

无论您思考/搜索多长时间,您总是在提出问题后立即给出答案。

我可以通过故意误用 try/catch 来解决这个问题,所以我遍历了这个结构,尝试从每个项目中创建一个对象,就好像它是一个组件一样,如果出错,将它复制到我的快照中结构体。我还必须将它存储在不同的范围内,在我的情况下,我使用了 session,因为如果我让它进入默认变量,就会有一个循环引用,导致一个具有无限数量的子结构的结构。

编辑:这不会像我想的那样做,见下文

<cfset session.varSnapShot = StructNew()>
<cfset loopList = StructKeyList(variables)>
<cfloop from="1" to="#ListLen(loopList)#" index="i">
    <cftry>
        <cfobject name="x#i#" component="#variables[ListGetAt(loopList,i)]#">
        <cfcatch>
            <cfset session.varSnapShot[ListGetAt(loopList,i)]= variables[ListGetAt(loopList,i)]>
        </cfcatch>
    </cftry>
</cfloop>

编辑:由于上面实际上并没有做一个深拷贝(感谢 Leigh)我想出了这个:

<cfloop from="1" to="#ListLen(loopList)#" index="i">
    <cfset metaData = GetMetaData(variables[ListGetAt(loopList,i)])>
    <cfif isStruct(metaData) AND isDefined("metaData.type") AND metaData.type EQ "component">
    <cfelse>
        <cfset session.varSnapShot[ListGetAt(loopList,i)]= duplicate(variables[ListGetAt(loopList,i)])>
    </cfif>
</cfloop>

这确实会进行深层复制,但如果组件低于对象的第一级,这仍然是一个问题。我想创建一个递归方法,但是星期五的下班时间过去了一个半小时。相反,我会在酒吧杀死脑细胞,如果我不忘记的话,可能会在星期一用递归方法更新它。

于 2011-09-16T22:45:27.730 回答