在8之前的ColdFusion版本中,如果结构中有任何组件,则复制函数会抛出错误。在8及以后它可以工作,但复制组件时会出现问题。
所以,我需要的是一种创建忽略组件的结构的深层副本的方法。出于我的目的,它是用于调试的,我需要在代码中的特定点处获得变量范围的快照,因此效率并不重要,因为这将永远不会使其脱离开发环境。目前使用CF 7,如果只是解决这个问题,我会采取8个优惠,但我不控制升级:(
答案 0 :(得分:5)
当你开始杀死脑细胞时,我对一个递归函数进行了尝试;)它排除了组件和java / com对象。 MX7都不能复制。我将函数放入组件中以避免篡改variables
范围。然后将实例存储在request
范围内。
未经过严格测试。所以我相信还有改进的余地。
<强>用法强>
<cfset request.util = createObject("component", "Util")>
<cfset request.copy = request.util.duplicateStructMinusObjects(variables)>
<cfdump var="#request.copy#">
<强> Util.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>
答案 1 :(得分: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>
这会产生深层复制,但如果组件低于对象的第一级,则仍然会出现问题。我想创建一个递归方法,但是星期五的退出时间是一个半小时。我会在酒吧杀死脑细胞,如果我不忘记的话,也可以在星期一用递归方法更新它。